When calculating the space for each direction when the grid size is multiply by 1.5 the directions are wrong why? - c#

If the grid is 10x10 or 23x7 it's working fine but when the grid have 1.5 spaces between the cubes the directions sometimes are wrong.
This is the grid script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GridGenerator : MonoBehaviour
{
public GameObject gridBlock;
public int gridWidth = 10;
public int gridHeight = 10;
public GameObject[] allBlocks;
private GameObject[] wallsParents = new GameObject[4];
void Start()
{
wallsParents[0] = GameObject.Find("Top Wall");
wallsParents[1] = GameObject.Find("Left Wall");
wallsParents[2] = GameObject.Find("Right Wall");
wallsParents[3] = GameObject.Find("Bottom Wall");
GenerateGrid();
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
var findpath = GetComponent<PathFinder>();
findpath.FindPath();
}
public void AutoGenerateGrid()
{
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
for (int i = 0; i < allBlocks.Length; i++)
{
DestroyImmediate(allBlocks[i]);
}
var end = GameObject.FindGameObjectWithTag("End");
DestroyImmediate(end);
GenerateGrid();
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
var findpath = GetComponent<PathFinder>();
findpath.FindPath();
}
public void GenerateGrid()
{
for (int x = 0; x < gridWidth; x++)
{
for (int z = 0; z < gridHeight; z++)
{
GameObject block = Instantiate(gridBlock, Vector3.zero, gridBlock.transform.rotation) as GameObject;
block.transform.parent = transform;
block.transform.name = "Block";
block.transform.tag = "Blocks";
block.transform.localPosition = new Vector3(x * 1.5f, 0, z * 1.5f);
block.GetComponent<Renderer>().material.color = new Color(241, 255, 0, 255);
if (x == 0)//TOP
{
block.transform.parent = wallsParents[0].transform;
block.transform.name = "TopWall";
block.transform.tag = "Blocks";
}
else if (z == 0)//LEFT
{
block.transform.parent = wallsParents[1].transform;
block.transform.name = "LeftWall";
block.transform.tag = "Blocks";
}
else if (z == gridHeight - 1)//RIGHT
{
block.transform.parent = wallsParents[2].transform;
block.transform.name = "RightWall";
block.transform.tag = "Blocks";
}
else if (x == gridWidth - 1)//BOTTOM
{
block.transform.parent = wallsParents[3].transform;
block.transform.name = "BottomWall";
block.transform.tag = "Blocks";
}
}
}
}
}
On this line i'm adding the spaces between the cubes:
block.transform.localPosition = new Vector3(x * 1.5f, 0, z * 1.5f);
Then in another script i'm trying to find what directions next are possible to move to.
private void Directions()
{
GridGenerator gridgenerator = GetComponent<GridGenerator>();
Vector3 playerPosition;
playerPosition = player.localPosition;
if (playerPosition.x > 0)
{
// can go left
possibleDirections[0] = "Can go left";
}
else
{
possibleDirections[0] = "Can't go left";
}
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
{
// can go right
possibleDirections[1] = "Can go right";
}
else
{
possibleDirections[1] = "Can't go right";
}
if (playerPosition.z > 0)
{
// can go backward
possibleDirections[2] = "Can go backward";
}
else
{
possibleDirections[2] = "Can't go backward";
}
if (playerPosition.z + 1 < gridgenerator.gridHeight * 1.5f)
{
// can go backward
possibleDirections[3] = "Can go forward";
}
else
{
possibleDirections[3] = "Can't go forward";
}
}
possibleDirections is array string type
When the grid size is 10x10 without spaces between cubes this two lines:
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
if (playerPosition.z + 1 < gridgenerator.gridHeight * 1.5f)
Was:
if (playerPosition.x + 1 < gridgenerator.gridWidth)
if (playerPosition.z + 1 < gridgenerator.gridHeight)
But when i added the spaces between the cubes i tried to add to the gridgenerator.gridWidth and gridgenerator.gridHeight the * 1.5
But it didn't work so i tried also:
if (playerPosition.x + 1 < gridgenerator.gridWidth * (1 + 1.5))
if (playerPosition.z + 1 < gridgenerator.gridHeight * (1 + 1.5))
1 is the cube width and 1.5 is the space. But this is not working good either.
In the screenshot the player is in the top left corner facing up(forward)
He can't move forward but in the inspector it says "Can go forward" And should be "Can't go forward"
It only happens when there are spaces between the cubes.

This line is wrong:
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
Your gridWidth variable stores the number of cubes, not their collective spacing. You have 10 cubes representing move spaces, determining the out-of-bounds this value should remain constant (it's still only 10 cubes, even if they're spaced with a half-block worth of space between them).
You need to convert from the player's scene location (transform.position.x) to a board space location (likely dividing by the same multiplier used to space the cubes out).
Alternatively, the "this makes my soul cry" solution of doing this:
if (playerPosition.x + 1.5f < gridgenerator.gridWidth * 1.5f)
Because the next cube is 1.5 scene units away, not 1. And this makes my soul cry because it makes your code full of hard-coded 1.5f multipliers and offsets rather than keeping such things to a single, fixed, constant value stored Elsewhere and used sparingly.
Related:
possibleDirections[0] = "Can go left";
Why are you using stringly typed things? There are values called booleans for a reason...

Related

Issues with Steering Behavior Seperation

The problem
I am trying to procedurally generate dungeon rooms with random X, Y sizes inside of a radius (r). However, even after I validate that the starting grid (origin of the "room") is not in the same position as other origins after running the separation function there are rooms still building inside of each other.
Solutions I have tried
I tried using math to calculate an optimal radius that will be able to fit the average of all the room sizes * amount of rooms. However, the separation should hypothetically work with any radius (though I want to keep them relatively close in order to keep hallways short).
Code
All my code is based on one tile. This means that all calculations are using one tile, and will remain one tile until the very end, then I scale them up.
private void GenerateRooms(int amount)
{
// init sizes
Vector2[] room_sizes = new Vector2[amount];
for (int i = 0; i < amount; i++)
{
room_sizes[i] = new Vector2(Random.Range(minimum_room_height, maximum_room_height), Random.Range(minimum_room_width, maximum_room_width));
}
float biggest_room = calculations.CalculateBiggest(room_sizes);
Vector2[] room_points = new Vector2[amount];
Vector2[] used_points = new Vector2[amount];
float radius = calculations.CalculateAverage(room_sizes) * amount;
for (int i = 0; i < amount; i++)
{
do {
Vector2 test_point = new Vector2(Random.Range(-radius, radius), Random.Range(-radius, radius));
foreach (Vector2 point in used_points) {
if (test_point == point) {
continue;
} else {
room_points[i] = test_point;
used_points[i] = test_point;
break;
}
}
} while (Vector2.Distance(Vector2.zero, room_points[i]) < radius);
}
for (int i = 0; i < amount; i++)
{
//Vector2 origin = room_points[i];
Vector3 position = calculations.computeSeperate(room_points, room_points[i], biggest_room);
//position = new Vector3(position.x + origin.x, position.y + origin.y, 0);
Vector3Int location = tile_map.WorldToCell(position);
tile_map.SetTile(location, tile);
calculations.scaleUpRooms(position, room_sizes[i].x, room_sizes[i].y, tile_map, tile);
}
}
The above is code for calling all the functions and validating the points. Here are the important functions (calculation functions):
public Vector2 computeSeperate(Vector2[] point_array, Vector2 target_point, float minimum_distance)
{
int neighbor_count = 0;
for (int i = 0; i < point_array.Length; i++)
{
if (point_array[i] != target_point)
{
if (Vector2.Distance(target_point, point_array[i]) < minimum_distance * 2)
{
target_point.x += point_array[i].x - target_point.x;
target_point.y += point_array[i].y - target_point.y;
neighbor_count++;
}
}
}
if (neighbor_count == 0)
{
return target_point;
} else
{
target_point.x /= neighbor_count;
target_point.y /= neighbor_count;
target_point.x *= -1;
target_point.y *= -1;
target_point.Normalize();
return target_point;
}
}
public void scaleUpRooms(Vector2 base_point, float scale_x, float scale_y, Tilemap tile_map, Tile tile) // ex: 5x5
{
List<Vector2> Calculate(Vector2 size)
{
List<Vector2> results = new List<Vector2>();
for (int i = 0; i < size.y; i++)
for (int o = 0; o < size.x; o++)
results.Add(new Vector2(o, i) + (new Vector2(size.x % 2 != 0 ? .5f : 1, size.y % 2 != 0 ? .5f : 1) - (size / 2)));
string st = "";
for (int i = 0; i < results.Count; i++)
st += "\n" + results[i].ToString();
return results;
}
Vector2 desired_scale = new Vector2(scale_x, scale_y);
List<Vector2> Offsets = Calculate(desired_scale);
for (int i = 0; i < Offsets.Count; i++)
{
Vector3 position = base_point + Offsets[i];
Vector3Int location = tile_map.WorldToCell(position);
tile_map.SetTile(location, tile);
}
}

Why does the array I pass to my multithreading job struct act as a reference type?

I'm working on a unity project involving deformable terrain based on marching-cubes. It works by generating a map of density over the 3-dimensional coordinates of a terrain chunk and using that data to create a mesh representing the surface of the terrain. It has been working, however the process is very slow. I'm attempting to introduce multithreading to improve performance, but I've run into a problem that's left me scratching my head.
When I run CreateMeshData() and try to pass my density map terrainMap into the MarchCubeJob struct, it recognizes it as a reference type, not a value type. I've seemed to whittle down the errors to this one, but I've tried to introduce the data in every way I know how and I'm stumped. I thought passing a reference like this was supposed to create a copy of the data disconnected from the reference, but my understanding must be flawed. My goal is to pass each marchingcube cube into a job and have them run concurrently.
I'm brand new to multithreading, so I've probably made some newbie mistakes here and I'd appreciate if someone would help me out with a second look. Cheers!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
public class Chunk
{
List<Vector3> vertices = new List<Vector3>();
List<int> triangles = new List<int>();
public GameObject chunkObject;
MeshFilter meshFilter;
MeshCollider meshCollider;
MeshRenderer meshRenderer;
Vector3Int chunkPosition;
public float[,,] terrainMap;
// Job system
NativeList<Vector3> marchVerts;
NativeList<Vector3> marchTris;
MarchCubeJob instanceMarchCube;
JobHandle instanceJobHandle;
int width { get { return Terrain_Data.chunkWidth;}}
int height { get { return Terrain_Data.chunkHeight;}}
static float terrainSurface { get { return Terrain_Data.terrainSurface;}}
public Chunk (Vector3Int _position){ // Constructor
chunkObject = new GameObject();
chunkObject.name = string.Format("Chunk x{0}, y{1}, z{2}", _position.x, _position.y, _position.z);
chunkPosition = _position;
chunkObject.transform.position = chunkPosition;
meshRenderer = chunkObject.AddComponent<MeshRenderer>();
meshFilter = chunkObject.AddComponent<MeshFilter>();
meshCollider = chunkObject.AddComponent<MeshCollider>();
chunkObject.transform.tag = "Terrain";
terrainMap = new float[width + 1, height + 1, width + 1]; // Weight of each point
meshRenderer.material = Resources.Load<Material>("Materials/Terrain");
// Generate chunk
PopulateTerrainMap();
CreateMeshData();
}
void PopulateTerrainMap(){
...
}
void CreateMeshData(){
ClearMeshData();
vertices = new List<Vector3>();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
for (int z = 0; z < width; z++) {
Debug.Log(x + ", " + y + ", " + z + ", begin");
Vector3Int position = new Vector3Int(x, y, z);
// Set up memory pointers
NativeList<Vector3> marchVerts = new NativeList<Vector3>(Allocator.TempJob);
NativeList<int> marchTris = new NativeList<int>(Allocator.TempJob);
NativeList<float> mapSample = new NativeList<float>(Allocator.TempJob);
// Split marchcube into jobs by cube
instanceMarchCube = new MarchCubeJob(){
position = position,
marchVerts = marchVerts,
marchTris = marchTris,
mapSample = terrainMap
};
// Run job for each cube in a chunk
instanceJobHandle = instanceMarchCube.Schedule();
instanceJobHandle.Complete();
// Copy data from job to mesh data
//instanceMarchCube.marchVerts.CopyTo(vertices);
vertices.AddRange(marchVerts);
triangles.AddRange(marchTris);
// Dispose of memory pointers
marchVerts.Dispose();
marchTris.Dispose();
mapSample.Dispose();
Debug.Log(x + ", " + y + ", " + z + ", end");
}
}
}
BuildMesh();
}
public void PlaceTerrain (Vector3 pos, int radius, float speed){
...
CreateMeshData();
}
public void RemoveTerrain (Vector3 pos, int radius, float speed){
...
CreateMeshData();
}
void ClearMeshData(){
vertices.Clear();
triangles.Clear();
}
void BuildMesh(){
Mesh mesh = new Mesh();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
meshFilter.mesh = mesh;
meshCollider.sharedMesh = mesh;
}
private void OnDestroy(){
marchVerts.Dispose();
marchTris.Dispose();
}
}
// Build a cube as a job
[BurstCompile]
public struct MarchCubeJob: IJob{
static float terrainSurface { get { return Terrain_Data.terrainSurface;}}
public Vector3Int position;
public NativeList<Vector3> marchVerts;
public NativeList<int> marchTris;
public float[,,] mapSample;
public void Execute(){
//Sample terrain values at each corner of cube
float[] cube = new float[8];
for (int i = 0; i < 8; i++){
cube[i] = SampleTerrain(position + Terrain_Data.CornerTable[i]);
}
int configIndex = GetCubeConfiguration(cube);
// If done (-1 means there are no more vertices)
if (configIndex == 0 || configIndex == 255){
return;
}
int edgeIndex = 0;
for (int i = 0; i < 5; i++){ // Triangles
for (int p = 0; p < 3; p++){ // Tri Vertices
int indice = Terrain_Data.TriangleTable[configIndex, edgeIndex];
if (indice == -1){
return;
}
// Get 2 points of edge
Vector3 vert1 = position + Terrain_Data.CornerTable[Terrain_Data.EdgeIndexes[indice, 0]];
Vector3 vert2 = position + Terrain_Data.CornerTable[Terrain_Data.EdgeIndexes[indice, 1]];
Vector3 vertPosition;
// Smooth terrain
// Sample terrain values at either end of current edge
float vert1Sample = cube[Terrain_Data.EdgeIndexes[indice, 0]];
float vert2Sample = cube[Terrain_Data.EdgeIndexes[indice, 1]];
// Calculate difference between terrain values
float difference = vert2Sample - vert1Sample;
if (difference == 0){
difference = terrainSurface;
}
else{
difference = (terrainSurface - vert1Sample) / difference;
}
vertPosition = vert1 + ((vert2 - vert1) * difference);
marchVerts.Add(vertPosition);
marchTris.Add(marchVerts.Length - 1);
edgeIndex++;
}
}
}
static int GetCubeConfiguration(float[] cube){
int configurationIndex = 0;
for (int i = 0; i < 8; i++){
if (cube[i] > terrainSurface){
configurationIndex |= 1 << i;
}
}
return configurationIndex;
}
public float SampleTerrain(Vector3Int point){
return mapSample[point.x, point.y, point.z];
}
}

Unity Converting Microphone input into Hertz

I'm working on a Unity app that has some Microphone controls. At one point, I have to convert the Microphone input into Hertz (Hz) values and show them to the user. Now, I did some research and I made the following script for this purpose:
int amountSamples = 1024;
void Start ()
{
_fSample = AudioSettings.outputSampleRate;
}
void Update() {
if (focused && Initialized) {
if (Microphone.IsRecording(selectedDevice) && recording) {
spectrumData = GetSpectrumAnalysis();
if (spectrumCurve.keys.Length <= spectrumData.Length) {
float keyTimeValue = 0;
float currentHighestKeyTime = 0;
//create a curvefield if none exists
spectrumCurve = new AnimationCurve();
for (int t = 0; t < spectrumData.Length; t++) {
spectrumCurve.AddKey(1 / spectrumData.Length + t, spectrumData[t]);
spectrumCurve.MoveKey(1 / spectrumData.Length + t, new Keyframe(1 / spectrumData.Length + t, keyTimeValue = spectrumData[t])); //update keyframe value
if (keyTimeValue > currentHighestKeyTime) {
currentHighestKeyTime = keyTimeValue;
}
}
HighestKeyTimeValue = currentHighestKeyTime;
float freqN = HighestKeyTimeValue;
float f = freqN * (_fSample / 2) / amountSamples;
Debug.Log(f); //hz
}
}
}
audioSource.volume = 1;
}
And the GetSpectrumAnalysis()
public float[] GetSpectrumAnalysis ()
{
float[] dataSpectrum = new float[amountSamples];
audioSource.GetSpectrumData (dataSpectrum, 0, FFTWindow.BlackmanHarris);
for (int i = 0; i <= dataSpectrum.Length - 1; i++)
{
dataSpectrum[i] = Mathf.Abs (dataSpectrum[i] * sensitivity);
}
return dataSpectrum;
}
Now, with this code, the Hz value should be calculated in float f, it does work but the Hz values aren't too accurate, for example, I'm getting 400-500 Hz where I should get around 880 Hz. Similarly I'm getting 130 Hz instead of 220 Hz, etc.. So, I have 2 issues: I'm getting less Hz then I should and the Hz value is jumping too much and too fast so it's not consistent even if the sound playing is constant. Any idea how to improve this code? Where did I made a mistake?
EDIT
Check my answer for the solution.
Ok, nevermind, I found the solution, maybe this will help someone stumbling across this thread, change GetSpectrumAnalysis method to this:
public float test() {
float Threshold = 0.02f;
float[] dataSpectrum = new float[amountSamples];
audioSource.GetSpectrumData(dataSpectrum, 0, FFTWindow.BlackmanHarris); //Rectangular
float maxV = 0;
var maxN = 0;
for (int i = 0; i < amountSamples; i++) {
if (!(dataSpectrum[i] > maxV) || !(dataSpectrum[i] > Threshold)) {
continue;
}
maxV = dataSpectrum[i];
maxN = i; // maxN is the index of max
}
float freqN = maxN; // pass the index to a float variable
if (maxN > 0 && maxN < amountSamples - 1) { // interpolate index using neighbours
var dL = dataSpectrum[maxN - 1] / dataSpectrum[maxN];
var dR = dataSpectrum[maxN + 1] / dataSpectrum[maxN];
freqN += 0.5f * (dR * dR - dL * dL);
}
return freqN * (_fSample / 2) / amountSamples; // convert index to frequency
}
Then just call this in the update method like this:
Text.text = test().ToString("00");
For more info check out this thread: Unity answers

Replacing hexagons with destroyed hexagons

I want to replace the destroyed hexagons with other standing hexagons. Existing hexagons should fall from the top. For example if I destroy (0,2) positioned hexagon in the picture below, the top left hexagon which position of that hexagon is (0,0) should be moved to (0,2) position and i should create a new hexagon and put it on (0,0) which is empty now because we moved the hexagon on (0,0) to (0,2) earlier.
I have a two dimensional array that stores all the references of hexagons with an index of the hexagon's coordinate (x,y).
--IMPORTANT--
Moving the objects is not important. The important part is we have to know which hexagon will be replaced with another. We have to tell the ARRAY that we changed those hexagons and the hexagons that were just moved or created should have exactly one reference in the index of their new (x,y) positions.
VIDEO FOR BETTER EXPLAINING WHAT I WANT TO DO
https://www.youtube.com/watch?v=QYhq0qwFmmY
Any ideas or help would be appreciated!
Hexagon Coordinate system (ignore red arrows)
public void CreateGrid(int gridWidth, int gridHeight)
{
for (int y = 0; y < gridHeight; y++)
{
for (int x = 0; x < gridWidth; x++)
{
GameObject Hexagon = Instantiate(HexagonPre, Vector2.zero, Quaternion.identity, HexGrid);
int RandColor = Random.Range(0, 5);
if (RandColor == 0)
{
Hexagon.GetComponent<SpriteRenderer>().color = Color.blue;
}
else if (RandColor == 1)
{
Hexagon.GetComponent<SpriteRenderer>().color = Color.red;
}
else if (RandColor == 2)
{
Hexagon.GetComponent<SpriteRenderer>().color = Color.green;
}
else if (RandColor == 3)
{
Hexagon.GetComponent<SpriteRenderer>().color = Color.yellow;
}
else if (RandColor == 4)
{
Hexagon.GetComponent<SpriteRenderer>().color = Color.cyan;
}
Vector2 gridPos = new Vector2(x, y);
Hexagon.transform.position = CalcWorldPos(gridPos);
Hexagon.GetComponent<HexCoordinates>().Coordinates = new Vector2Int(x, y);
Hexagon.transform.name = "X: " + x + " | Y: " + y;
}
}
}
Code for destroying hexagons
if (MatchedColors == 2)
{
if(!HexToBeDestroyed.Contains(Hexagons[x, y].gameObject))
HexToBeDestroyed.Add(Hexagons[x, y].gameObject);
if (!HexToBeDestroyed.Contains(Hexagons[x - 1, y].gameObject))
HexToBeDestroyed.Add(Hexagons[x - 1, y].gameObject);
if (!HexToBeDestroyed.Contains(Hexagons[x - 1, y - 1].gameObject))
HexToBeDestroyed.Add(Hexagons[x - 1, y - 1].gameObject);
}
MatchedColors = 0;
}
}
}
}
foreach (GameObject G in HexToBeDestroyed)
{
if (G != null)
{
Destroy(G.gameObject);
}
}
Explanation for code is in comments:
void HexagonFall(GameObject[,] hexArray)
{
// Handle fall for base columns and for offset columns
for (int offset = 0 ; offset < 2 ; offset++)
{
// Handle fall for each column at current offset
for (int x = 0 ; x < hexArray.GetLength(0) ; x++)
{
int bottomYIndex = hexArray.GetLength(1) - offset - 1;
// List of indices of where each hexagon in that column will come from.
// We will fill from bottom to top.
List<Vector2Int> sourceIndices = new List<Vector2Int>();
for (int y = bottomYIndex ; y >= 0 ; y-=2)
{
// HexExists returns true if the hex isn't empty.
// Something along the lines of ` return input!=null; `
// depending on what "empty" hexes look like in the array
if (HexExists(hexArray[x,y]))
{
sourceIndices.Add(new Vector2Int(x,y));
}
}
// We have a list of where to get each bottom hexes from, now do the move/create
for (int y = bottomYIndex; y >= 0 ; y-=2)
{
if (sourceIndices.Count > 0)
{
// If we have any available hexes in column,
// use the bottommost one (at index 0)
hexArray[x,y] = hexArray[sourceIndices[0].x, sourceIndices[0].y];
// We have now found a home for hex previously at sourceIndices[0].
// Remove that index from list so hex will stay put.
sourceIndices.RemoveAt(0);
}
else
{
// Otherwise, we need to generate a new hex
hexArray[x,y] = MakeNewHexAt(new Vector2Int(x,y));
}
// Tell the hex about its new home
hexArray[x,y].GetComponent<HexCoordinates>().Coordinates = new Vector2Int(x, y);
hexArray[x,y].transform.name = "X: " + x + " | Y: " + y;
}
}
}
}
In your hex destroying code, I would change HexToBeDestroyed to be a List of Vector2Int so you can set the array references to null immediately when you Destroy the gameobject:
List<Vector2Int> HexToBeDestroyed = new List<Vector2Int>();
// ...
if (MatchedColors == 2)
{
if(!HexToBeDestroyed.Contains(new Vector2Int(x, y))
HexToBeDestroyed.Add(new Vector2Int(x, y));
if (!HexToBeDestroyed.Contains(new Vector2Int(x - 1, y))
HexToBeDestroyed.Add(new Vector2Int(x - 1, y));
if (!HexToBeDestroyed.Contains(new Vector2Int(x - 1, y - 1)))
HexToBeDestroyed.Add(new Vector2Int(x - 1, y - 1));
}
// ...
foreach (Vector2Int V in HexToBeDestroyed)
{
if (Hexagons[V.x,V.y] != null)
{
Destroy(Hexagons[V.x,V.y]);
Hexagons[V.x,V.y] = null;
}
}
As far as moving the hexes goes, I would add this in the Update of HexCoordinates:
float fallSpeed = 0.5f;
Vector2 goalWorldPosition = GS.CalcWorldPos(Coordinates);
transform.position = Vector2.MoveTowards(transform.position, goalWorldPosition, fallSpeed * Time.deltaTime);

How to debug a recursive function in unity C#

Im trying to make a maze generator using recursion. Its not working how its supposed to work, and Im trying to figure out where the error is. So I want to step through the recursion 1 iteration at the time. How do I do this?
private void DevideRecursive(int pMinX, int pMaxX, int pMinY, int pMaxY)
{
int randomX = Random.Range(pMinX +1, pMaxX);
int randomY = Random.Range(pMinY +1, pMaxY);
int randomWall = Random.Range(0, 4);
List<GameObject> WalllistX1 = new List<GameObject>();
List<GameObject> WalllistX2 = new List<GameObject>();
List<GameObject> WalllistY1 = new List<GameObject>();
List<GameObject> WalllistY2 = new List<GameObject>();
List<List<GameObject>> MainWallList = new List<List<GameObject>>();
MainWallList.Add(WalllistX1);
MainWallList.Add(WalllistX2);
MainWallList.Add(WalllistY1);
MainWallList.Add(WalllistY2);
//// add a wall on a random x coordinate
for (int x = pMinX; x < pMaxX; x++)
{
GameObject wall = Instantiate(WallHor);
wall.transform.position = new Vector2(tilesize * x + tilesize / 2, tilesize * randomY);
if (x < randomX)
{
WalllistX1.Add(wall);
}
else
{
WalllistX2.Add(wall);
}
}
//// add a wall on a random y coordinate
for (int y = pMinY; y < pMaxY ; y++)
{
GameObject wall = Instantiate(WallVer);
wall.transform.position = new Vector2(tilesize * randomX, tilesize * y + tilesize / 2);
if (y < randomY)
{
WalllistY1.Add(wall);
}
else
{
WalllistY2.Add(wall);
}
}
//make a hole in 3 out of tht 4 walls randomly
for (int i = 0; i < MainWallList.Count; i++)
{
if (randomWall != i)
{
RemoveWall(MainWallList[i]);
}
}
////
////
//// If either of the walls have a cell with only 1 grid stop the recursion
Debug.Log("randomX - pMinX:" + (randomX - pMinX));
Debug.Log("pMaxY - randomY:" + (pMaxY - randomY));
Debug.Log("pMaxX - randomX:" + (pMaxX - randomX));
Debug.Log("randomY - pMinY:" + (randomY - pMinY));
if (!(randomX - pMinX <= 1) || !(pMaxY - randomY <= 1))
{
Debug.Log("a");
DevideRecursive(pMinX, randomX, randomY, pMaxY);
}
else
{
return;
}
if (!(pMaxX - randomX <= 1) || !(pMaxY - randomY <= 1))
{
Debug.Log("b");
DevideRecursive(randomX, pMaxX, randomY, pMaxY);
}
else
{
return;
}
if (!(randomX - pMinX <= 1 )|| !(randomY - pMinY <= 1))
{
Debug.Log("c");
DevideRecursive(pMinX, randomX, pMinY, randomY);
}
else
{
return;
}
if (!(pMaxX - randomX <= 1) || !(randomY - pMinY <= 1))
{
Debug.Log("d");
DevideRecursive(randomX, pMaxX, pMinY, randomY);
}
else
{
return;
}
}
This is my Recursive method. It get called in the Start function.
The method creates 2 random walls(1 vertical, 1 horizontal). Which devides the room in 4 smaller rooms. Then it does the same thing for those rooms.
Any help is appriciated
You could modify the function to use async.
using System.Threading.Tasks;
void Start () {
DevideRecursive( ..params.. );
}
private async void DevideRecursive(int pMinX, int pMaxX, int pMinY, int pMaxY) {
// code
while (!Input.GetKeyDown(KeyCode.Space))
await Task.Yield ();
// code
DevideRecursive( .. params .. );
return
}
More infomation on aysnc in Unity here.
An IEnumerator could also be used, which gives you the option to control the function externally.

Categories