How to debug a recursive function in unity C# - 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.

Related

A function in my program seems like it should work but occasionally gives the wrong output

I wrote a function that checks for a given cell in a grid if it is a legal move following the rules of the board-game called Reversi otherwise known as Othello. The rules are that a circle can only be placed on the grid whenever the newly placed circle and a previous placed circle bounds one of the opponents circles. The majority of the time the function gives the right output (i.e. true when it is a legal move and false when it is a legal move), but some moves that are legal by the previously stated rules are not deemed as a legal move by the function.
I've tried to use the console to check at every step at which cell the function is currently looking and what the value of the cell is to determine what goes wrong. This has only led me to being even more confused.
The following code is the doomed-function:
bool legalMove(int row, int col)
{
// Check if the cell is occupied
if (board[row,col] != 0)
return false;
// Check if there's an opponents circle somewhere around it
for (int i = -1; i<=1; i++)
for (int j = -1; j<=1; j++)
{
if (i == 0 && j == 0)
continue;
int currentRow = row + i;
int currentCol = col + j;
if (currentRow >= 0 && currentRow < board.GetLength(0) && currentCol >= 0 && currentCol < board.GetLength(1) && board[currentRow,currentCol] == -turn)
{
// Now we know that there's an opponents circle somewhere around this space, we now check if it can be captured
while(true)
{
currentRow += i;
currentCol += j;
Console.WriteLine($"currentRow: {currentRow}, currentCol: {currentCol}, value: {board[currentRow,currentCol]}");
if (currentRow < 0 || currentRow >= board.GetLength(0) || currentCol < 0 || currentCol >= board.GetLength(1) || board[currentRow, currentCol] == 0)
return false; // Outside of the board or an empty space
else if (board[currentRow,currentCol] == turn)
return true; // No empty spaces between our cell and another cell of ours
}
}
}
return false; // No cell found around ours
}
What am I missing here?
Thanks in advance!
EDIT:
The entire program is the following (hope it can help):
/* TO-DO
* Make function out of no legal move and tidy up
* Calculate amount of circles of player to determine the winner
* Make victory label better
!!!Tidy up flipCircles method and fix legalMove method
Create a slider and make it change the gridSize
Make GUI change empty space when board gets smaller or bigger
Tidy up the 2x calling to check what the score is
*/
// Library imports
using System;
using System.Drawing;
using System.Security.Policy;
using System.Windows.Forms;
// Game class
class Game : Form
{
// Declare variables
private Board board;
private Button newGame, help;
private Font font;
private Label countRed, countBlue, gameState;
private TrackBar sizeBoard;
public int gridSize = 6;
public Game()
{
// Set the form properties
ClientSize = new Size(520, 670); Text = "Reversi";
// Creating the GUI and adding it to the form
newGame = new Button(); Controls.Add(newGame);
help = new Button(); Controls.Add(help);
font = new Font("Arial", 14);
countBlue = new Label(); Controls.Add(countBlue); countBlue.Font = font;
countRed = new Label(); Controls.Add(countRed); countRed.Font = font;
gameState = new Label(); Controls.Add(gameState); gameState.Font = font;
board = new Board(gridSize); Controls.Add(board);
// Settings of the GUI
newGame.Size = new Size(100, 30); newGame.Location = new Point(150, 10); newGame.Text = "New Game"; newGame.BackColor = Color.LightSlateGray;
help.Size = new Size(100, 30); help.Location = new Point(270, 10); help.Text = "Help"; help.BackColor = Color.LightSlateGray;
countBlue.Size = new Size(110, 30); countBlue.Location = new Point(150, 50); countBlue.Text = $"{board.countBlue} stones"; countBlue.ForeColor = Color.CornflowerBlue;
countRed.Size = new Size(110, 30); countRed.Location = new Point(150, 90); countRed.Text = $"{board.countRed} stones"; countRed.ForeColor = Color.Firebrick;
gameState.Size = new Size(150, 30); gameState.Location = new Point(270, 90); gameState.Text = $"{board.playersTurn}";
// Events //
// Label events
newGame.Click += reset;
help.Click += calculateHelp;
// Board events
board.MouseClick += clicked;
//Paint event
Paint += paint;
}
// Event-handlers //
// Label event-handlers
private void reset(object e, EventArgs ea)
{
board.Reset();
countBlue.Text = $"{board.countBlue} stones";
countRed.Text = $"{board.countRed} stones";
gameState.Text = $"{board.playersTurn}";
}
private void calculateHelp(object e, EventArgs ea)
{
board.SetHelp();
}
// Board event-handlers
private void clicked(object e, MouseEventArgs mea)
{
board.Clicked(mea.Location);
countBlue.Text = $"{board.countBlue} stones";
countRed.Text = $"{board.countRed} stones";
gameState.Text = $"{board.playersTurn}";
// Now check if there's a legalMove if not
//if (timesNoLegalMove > 1)
gameState.Text = $"{board.playersTurn}";
}
// Paint event-handler
private void paint(object e, PaintEventArgs pea)
{
Graphics gr = pea.Graphics;
gr.FillEllipse(Brushes.CornflowerBlue, 100, 45, 31, 31);
gr.FillEllipse(Brushes.Firebrick, 100, 85, 31, 31);
}
}
// Board class
class Board : Label
{
// Declare all global variables used in this class
private int[,] board;
private int size;
private int turn = 1; // 1 is blue, -1 is red
private bool legalMoveExists = true;
public int timesNoLegalMove = 0;
private bool help = false;
// Create the board and set settings + events
public Board(int gridSize)
{
size = gridSize;
Size = new Size(size * 50, size * 50);
Location = new Point(10 + (25 * (10 - size)), 120 + (25 * (10 - size)));
BackColor = Color.White;
board = new int[size, size];
startingState();
Paint += Draw;
}
// Sets the values of the center 4 squares to that of the starting circles
private void startingState()
{
board[(size / 2)-1, (size / 2)-1] = 1;
board[(size / 2), (size / 2)] = 1;
board[(size / 2), (size / 2) - 1] = -1;
board[(size / 2) - 1, (size / 2)] = -1;
}
// Resets the board when New Game is clicked
public void Reset()
{
for (int row = 0; row < board.GetLength(0); row++)
for (int col = 0; col < board.GetLength(1); col++)
board[row, col] = 0;
startingState();
turn = 1;
Invalidate();
}
public void SetHelp()
{
if (help)
help = false;
else
help = true;
Invalidate();
}
public string playersTurn
{
get
{
if (turn == 1)
return "It's Blue's turn";
if (turn == -1)
return "It's Red's turn";
else
{
if (countBlue > countRed)
return "Blue has won the game!";
if (countRed > countBlue)
return "Red has won the game!";
else
return "It's a draw!";
}
}
}
public int countRed
{
get
{
return board.Cast<int>().Count(n => n == -1);
}
}
public int countBlue
{
get
{
return board.Cast<int>().Count(n => n == 1);
}
}
bool legalMove(int row, int col)
{
// Check if the cell is occupied
if (board[row,col] != 0)
return false;
// Check if there's an opponents circle somewhere around it
for (int i = -1; i<=1; i++)
for (int j = -1; j<=1; j++)
{
if (i == 0 && j == 0)
continue;
int currentRow = row + i;
int currentCol = col + j;
if (currentRow >= 0 && currentRow < board.GetLength(0) && currentCol >= 0 && currentCol < board.GetLength(1) && board[currentRow,currentCol] == -turn)
{
// Now we know that there's an opponents circle somewhere around this space, we now check if it can be captured
while(true)
{
currentRow += i;
currentCol += j;
if (currentRow < 0 || currentRow >= board.GetLength(0) || currentCol < 0 || currentCol >= board.GetLength(1) || board[currentRow, currentCol] == 0)
return false; // Outside of the board or an empty space
else if (board[currentRow,currentCol] == turn)
return true; // No empty spaces between our cell and another cell of ours
}
}
}
return false; // No cell found around ours
}
private void flipCircles(int row, int col)
{
// Check all eight directions from the current position
for (int r = row - 1; r <= row + 1; r++)
{
for (int c = col - 1; c <= col + 1; c++)
{
// Skip the current position
if (r == row && c == col)
continue;
int rr = r;
int cc = c;
// Check if the next position in this direction is a valid position on the board
// and if it is occupied by the opponent's piece
if (rr >= 0 && rr < board.GetLength(0) && cc >= 0 && cc < board.GetLength(1) && board[rr, cc] == -turn)
{
// Keep moving in this direction until we find the current player's piece or an empty cell
while (true)
{
rr += r - row;
cc += c - col;
// If we have reached an invalid position or an empty cell, break out of the loop
if (rr < 0 || rr >= board.GetLength(0) || cc < 0 || cc >= board.GetLength(1) || board[rr, cc] == 0)
break;
// If we have found the current player's piece, flip all the pieces between the current position and the player's piece
if (board[rr, cc] == turn)
{
while (rr != r || cc != c)
{
rr -= r - row;
cc -= c - col;
board[rr, cc] = turn;
}
break;
}
}
}
}
}
}
// Sets the value of a clicked cell to either 1 (Blue), or -1 (Red)
public void Clicked(Point mea)
{
int rowClicked = mea.X / 50;
int colClicked = mea.Y /50;
if (legalMove(rowClicked, colClicked))
{
board[rowClicked, colClicked] = turn;
flipCircles(rowClicked, colClicked);
help = false;
turn = -turn;
legalMoveExists = false;
Invalidate();
}
}
// Draws the entire board and all circles
void Draw(object e, PaintEventArgs pea)
{
Graphics gr = pea.Graphics;
legalMoveExists = false;
for (int row = 0; row < board.GetLength(0); row++)
for (int col = 0; col < board.GetLength(1); col++)
{
// Draw the background tiles
if (row % 2 == 0 && col % 2 == 0 || row % 2 != 0 && col % 2 != 0)
gr.FillRectangle(Brushes.DarkGray, 50 * row, 50 * col, 50, 50);
// Draw circles
if (board[row, col] == 1) // Blue circles
gr.FillEllipse(Brushes.CornflowerBlue, 50 * row - 1, 50 * col - 1, 51, 51);
else if (board[row, col] == -1) // Red circles
gr.FillEllipse(Brushes.Firebrick, 50 * row - 1, 50 * col - 1, 51, 51);
// Check for legal moves and draw help circles if the help button has been pressed
else if (legalMove(row, col))
{
legalMoveExists = true;
timesNoLegalMove = 0;
if (help) // Help circles
gr.DrawEllipse(Pens.Black, 50 * row + 9, 50 * col + 9, 31, 31);
}
}
// Make this a function
if (!legalMoveExists)
{
turn = -turn;
timesNoLegalMove++;
Invalidate();
if (timesNoLegalMove > 1)
turn = 0;
}
}
}
// Main run
class Program
{
static void Main()
{
Application.Run(new Game());
}
}
Your question states that the function you wrote to scan the surrounding cells is failing sporadically and that it's difficult to diagnose. It was easy to reproduce the failures by running your code, but I wasn't able to see an obvious way to effectively debug it.
It "might" be more effective to improve the algorithm where it's more methodical in how it inspects the surrounding cells in the first place, which would also be easier to debug if necessary. One solid way to do this would be to use custom Iterators where you could use a standard foreach pattern to inspect virtual "lines" radiating in the eight directions. At each 'yield' you can check to see whether a determination can be made in terms of either a "legal move" or a "capture".
Here's a proof-of-concept grid that is intended to demonstrate how the iterators work. It doesn't evaluate the cells in terms of game play in any way but you can see how it would lend itself to doing that. The idea here is to click any cell and observe the markup of U-R-D-L. It may also help to see it working so you can clone this sample and set breakpoints.
Left, Right, Up, Down iterator examples are shown - diagonals would follow the same pattern. The mouse down control passes the starting cell coordinate position as a Point:
public IEnumerable<Point> CellsUp(Point point)
{
while (true)
{
point = new Point(point.X, point.Y - 1);
if (point.Y < 0) break;
yield return point;
}
}
public IEnumerable<Point> CellsRight(Point point, int max)
{
while (true)
{
point = new Point(point.X + 1, point.Y);
if (point.X == max) break;
yield return point;
}
}
public IEnumerable<Point> CellsDown(Point point, int max)
{
while (true)
{
yield return point;
point = new Point(point.X, point.Y + 1);
if (point.Y == max) break;
}
}
public IEnumerable<Point> CellsLeft(Point point)
{
while (true)
{
yield return point;
point = new Point(point.X - 1, point.Y);
if (point.X < 0) break;
}
}
The code lays the groundwork for a methodical scan outward from any given point.
private void legalMoveIterationStub(object? sender, EventArgs e)
{
clear();
if(sender is Control control)
{
control.BackColor = Color.Blue;
control.Refresh();
var pos = board.GetCellPosition(control);
var pt = new Point(pos.Column, pos.Row);
Control ctrl;
foreach (var point in CellsUp(pt))
{
ctrl = board.GetControlFromPosition(point.X, point.Y);
ctrl.Text = "U";
ctrl.Refresh();
Thread.Sleep(DEMO_DELAY_MS);
// This is where the cell inspects e.g. for "empty square"
// or color. Chances are, some condition will be met
// and you will break from here rather than iterate
// all the way to the edge of the board each time.
}
foreach (var point in CellsRight(pt, board.ColumnCount))
{
ctrl = board.GetControlFromPosition(point.X, point.Y);
ctrl.Text = "R";
ctrl.Refresh();
Thread.Sleep(DEMO_DELAY_MS);
}
foreach (var point in CellsDown(pt, board.ColumnCount))
{
ctrl = board.GetControlFromPosition(point.X, point.Y);
ctrl.Text = "D";
ctrl.Refresh();
Thread.Sleep(DEMO_DELAY_MS);
}
foreach (var point in CellsLeft(pt))
{
ctrl = board.GetControlFromPosition(point.X, point.Y);
ctrl.Text = "L";
ctrl.Refresh();
Thread.Sleep(DEMO_DELAY_MS);
}
}
}
The demo board has been mocked like this for testing purposes:
public partial class Game : Form
{
public Game()
{
InitializeComponent();
for (int col = 0; col < board.ColumnCount; col++)
{
for (int row = 0; row < board.RowCount; row++)
{
var tile = new Label
{
BorderStyle = BorderStyle.FixedSingle,
Anchor = (AnchorStyles)0xF,
Margin = new Padding(1),
TextAlign = ContentAlignment.MiddleCenter
};
board.Controls.Add(tile, col, row);
tile.MouseDown += legalMove;
}
}
}
void clear()
{
foreach (Control control in board.Controls)
{
control.Text = string.Empty;
control.BackColor = SystemColors.Control;
}
board.Refresh();
}
.
.
.
}

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);
}
}

How can I reduce the gaps between objects?

At the top :
[Range(10, 100)]
public int gap = 10;
private int oldGapValue = 0;
And in Update :
private void Update()
{
if(gap > oldGapValue)
{
for(int i = 0; i < numberOfUnits; i++)
{
units[i].transform.position = (i + 1f) * new Vector3(gap, 0, 0);
}
oldGapValue = gap;
}
else
{
}
This working for adding gaps. but in the else part I want to reduce the gaps between the objects.
I tried this but this is not working good, now it's working fine when reducing the gaps but now when adding gaps it's not working good it's adding gaps but also double the units objects until I stop adding gaps it's all stuttering.
if(gap > oldGapValue)
{
for(int i = 0; i < numberOfUnits; i++)
{
units[i].transform.position = (i + 1f) * new Vector3(gap, 0, 0);
}
oldGapValue = gap;
}
else
{
for (int i = 0; i < numberOfUnits; i++)
{
units[i].transform.position = (i + 1f) * new Vector3(-gap, 0, 0);
}
}
It looks like you're trying to space objects, by the value of gap, every single frame because of your logic.
Might I suggest a different approach and only change the object spacing when the value of gap actually changes. As an example, try this code:
[SerializeField]
[Range ( 10f, 100f )]
private float _gap = 10f;
private float _oldGap = 10f;
public float gap
{
get => _gap;
set
{
_oldGap = _gap;
Debug.Log ( $"New Gap Value {_gap}" );
for ( int i = 0; i < units.Length; i++ )
{
units [ i ].transform.position = new Vector3 ( (gap * i) + 1f, 0, 0 );
}
}
}
private void OnValidate ( )
{
if ( _gap != _oldGap )
gap = _gap;
}

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

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...

Unity Rectangle Overlapping

So I got this piece of code that fills the given area of specific size with floor tiles.
while (roomsPlaced < roomCount.maximum)
{
Vector3 randomPosition = RandomPosition();
int roomHeight = GetRandomNumber(8, 15);
int roomWidth = GetRandomNumber(6, 15);
if (OutOfMap(randomPosition, roomHeight,roomWidth))
{
continue;
}
if (roomsPlaced > 0) {
if (Overlaps(new Rect(randomPosition.x, randomPosition.y, roomWidth, roomHeight), roomPositions[roomPositions.Count -1]))
continue;
}
roomPositions.Add(new Rect(randomPosition.x, randomPosition.y, roomWidth, roomHeight));
for (int x = (int)randomPosition.x; x <= (int)randomPosition.x + roomWidth; x++)
{
for (int y = (int)randomPosition.y; y <= (int)randomPosition.y + roomHeight; y++)
{
if (x == randomPosition.x || y == randomPosition.y)
toInstantiate = floorTiles[Random.Range(0, floorTiles.Length)];
GameObject instance = Instantiate(toInstantiate, new Vector3(x, y, 0f), Quaternion.identity) as GameObject;
instance.transform.SetParent(boardHolder);
}
}
roomsPlaced++;
}
And here is function that should check if current rectangle overlaps the last rectangle on the list.
bool Overlaps(Rect rA, Rect rB)
{
return (rA.x < rB.x + rB.width && rA.x + rA.width > rB.x && rA.y < rB.y + rB.height && rA.y + rA.height > rB.y);
}
But still I have problem when some of my rooms overlap.
What am I doing wrong and what should I do to fix this problem ?
This sounds like you need to use the Overlaps method instead...
Yeeah. I just solved the problem by going through the whole list instead of picking last element on the list.

Categories