How to detect overlap from randomly generated prefabs [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a working script which randomly generates:
PosX, PosY, ScaleX and ScaleY
I have my randomly generated prefabs into parallel arrays. From that randomly resized and positioned cubes are generated. However since it is randomly generated how can i detect there is a overlap by code ? And when there is an overlap how can i delete it ?
I need help writing the code. Ive tried using raycasting and OnTriggerEnter but im too confused as to how to do it. Ive also seen using the
Physics.CheckCapsule
Physics.CapsuleCastAll
Physics.CheckSphere
Bounds.Intersect
But i don't know how to do it.
I don't know how to use Physics.OverlapSphere on arrays.
What am i supposed to do.
void Detect_Collision_Two(int i) {
bool isOverLapped = false;
Collider[] platformsInRange = Physics.OverlapSphere(platformPrefabPosition[i], scaleX[i]/2);
foreach(Collider col in platformsInRange) {
if(col.gameObject == platformPrefab) {
continue;
}
if
}
}
Edit
Attempt
These are the attempt i have tried to do using the math methods. Which checks the center position and takes into consideration of the width and height of the platform. Then using that information to compare with other platforms.
The second method is using the OverlapSphere , but i have no idea how to implement that.
Please help
void Platform_Position_Scale_Generator(int i) {
posX[i] = Random.Range(minPosRange, maxPosRange + 1);
posY[i] = Random.Range(minPosRange, maxPosRange + 1);
posZ[i] = 0;
scaleX[i] = Random.Range(minScaleRange, maxScaleRange + 1);
scaleY[i] = 1;
scaleZ[i] = 1;
}
void Platform_Generator(int i) {
platformPrefabPosition[i].x = posX[i];
platformPrefabPosition[i].y = posY[i];
platformPrefabPosition[i].z = posZ[i];
Instantiate(platformPrefab, platformPrefabPosition[i], Quaternion.identity);
platformPrefab.transform.localScale = new Vector3(scaleX[i], 1, 1);
}
// Error with this
void Detect_Collision(int i) {
for(int f = 0; f < i; f++) {
for(int s = f + 1; s < i; s++) {
bool xOverlap = (posX[s] > posX[f] && posX[s] < posX[f] + scaleX[i]) || (posX[f] > posX[s] && posX[f] < posX[s] + scaleX[i]);
bool yOverlap = (posY[s] > posY[f] && posY[s] < posY[f] + scaleY[i]) || (posY[f] > posY[s] && posY[f] < posY[s] + scaleY[i]);
if(xOverlap && yOverlap) {
Debug.Log("xOverlap: " + xOverlap + " yOverlap: " + yOverlap);
}
else {
//Debug.Log("xOverlap: " + xOverlap + " yOverlap: " + yOverlap);
}
}
}
}
void Detect_Collision_Two(int i) {
bool isOverLapped = false;
Collider[] platformsInRange = Physics.OverlapSphere(platformPrefabPosition[i], scaleX[i]/2);
foreach(Collider col in platformsInRange) {
if(col.gameObject == platformPrefab) {
continue;
}
if
}
}

you need to make an overlapSphere with your object position center as its center and bounds extent magnitude as its radius and check for all the colliders in this boundry if thier bounds intersect with new object bounds
bool isOverlapped = false;
Bounds bounds = renderer.bounds;
Collider[] cols = Physics.OverlapSphere(transform.position, bounds.extents.magnitude);
foreach(Collider col in cols) {
if (col.gameObject == gameObject) {
continue;
}
if (bounds.Intersects(col.gameObject.renderer.bounds)) {
isOverlapped = true;
break;
}
}
after this you can use the isOverlapped bool to destroy your object like this
if(isOverlapped)
Destroy (gameObject);

Related

Vertical Layout not working properly when children are instantiated - Unity

I have a GameObject with a vertical layout component, and when I instantiate its children for content, the children overlap with each other which means it does not follow the vertical layout order and just on top of each other (see the photo below).
The GameObject (parent)
The child (ArticleCard) that I instantiate or cloned also has a vertical layout because I wanted it to have a responsive height depending on the length of its children's texts. You can see it in the editor of the second photo.
The ArticleCard (clone)
Both the parent and the child that I instantiate or clone have vertical layout and content size fitter set to Min Size. The rest of the information about their inspector is in the two previous photos for reference.
But when I changed or tweaked just a single component like the padding in the vertical layout or anything in their inspector or re-arranged them in the hierarchy, even though I changed it back, the vertical layout suddenly worked just fine and removed the bug.
When the GameObjects are just instantiated, the vertical layout will not work, but when I edit or change just a single component, it will snap to how it is supposed to be. In this third photo, I unchecked and checked the Child Force Expand height value in the Vertical Layout Group, which snaps to how it is supposed to be.
ArticleCard (Clone)
This is the script for Instantiating the ArticleCard object, in the final if statement which checks if the name of the GameObject is "FireFacts".
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class TryInstantiate : MonoBehaviour
{
private GameObject articleTemplate, MG_ArticleTemplate, divider, objTxt, tipTxt, g;
[SerializeField] private GameData gameData;
//private string[] articleSplit;
private void OnEnable()
{
if (gameObject.name == "Articles")
{
articleTemplate = transform.GetChild(0).gameObject;
if (!(gameData.articlesList == null))
{
for (int i = 0; i < gameData.articlesList.Count; i++)
{
//articleSplit = gameData.articlesList[i].Split("#");
g = Instantiate(articleTemplate, transform);
g.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = gameData.getArticle(gameData.articlesList[i]).title;
g.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = "Published by " +
gameData.getPublisherDetail(gameData.articlesList[i]).type + " on " +
gameData.getArticle(gameData.articlesList[i]).date;
g.SetActive(true);
}
}
// Destroy(articleTemplate);
articleTemplate.SetActive(false);
}
else if (gameObject.name == "Objectives")
{
divider = transform.GetChild(0).gameObject;
objTxt = transform.GetChild(1).gameObject;
if (!(gameData.objectivesList == null))
{
for (int i = 0; i < gameData.objectivesList.Count; i++)
{
g = Instantiate(objTxt, transform);
g.transform.GetComponent<TextMeshProUGUI>().text = gameData.objectivesList[i];
g.SetActive(true);
g = Instantiate(divider, transform);
g.SetActive(true);
}
}
// Destroy(objTxt);
// Destroy(divider);
objTxt.SetActive(false);
//divider.SetActive(false);
}
else if (gameObject.name == "Clues")
{
divider = transform.GetChild(0).gameObject;
tipTxt = transform.GetChild(1).gameObject;
if (!(gameData.cluesList == null))
{
for (int i = 0; i < gameData.cluesList.Count; i++)
{
g = Instantiate(tipTxt, transform);
g.transform.GetComponent<TextMeshProUGUI>().text = gameData.cluesList[i];
g.SetActive(true);
g = Instantiate(divider, transform);
g.SetActive(true);
}
}
tipTxt.SetActive(false);
//divider.SetActive(false);
}else if(gameObject.name == "FireFacts")
{
MG_ArticleTemplate = transform.GetChild(0).gameObject;
//Debug.Log()
if (!(gameData.mgArticlesList == null))
{
for (int i = 0; i < gameData.mgArticlesList.Count; i++)
{
g = Instantiate(MG_ArticleTemplate, transform);
g.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = gameData.getMG_Article(gameData.mgArticlesList[i]).title;
g.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = "Published by <link=publisher><color=blue><u><b><font=\"Fredoka-Bold SDF\">" +
gameData.getMG_Publisher(gameData.mgArticlesList[i]).name + "</font></b></u></color></link> on <font=\"Fredoka-Bold SDF\">" +
gameData.getMG_Article(gameData.mgArticlesList[i]).date + "</font>";
g.transform.GetChild(3).GetComponent<TextMeshProUGUI>().text = gameData.getMG_Article(gameData.mgArticlesList[i]).description;
g.SetActive(true);
}
transform.GetComponent<VerticalLayoutGroup>().padding.top = 15;
transform.GetComponent<VerticalLayoutGroup>().spacing = 15;
}
}
}
private void OnDisable()
{
foreach (Transform clone in gameObject.transform)
{
if (clone.name == "ArticleCard(Clone)" || clone.name == "ObjectiveText(Clone)" || clone.name == "CluesText(Clone)" || clone.name == "Divider(Clone)")
{
Destroy(clone.gameObject);
}
}
}
}
I solved my problem by using Coroutines. The problem is fixed, or the layout is fixed every time I tweak or edit anything at runtime. I turned a layout off and then on via script, but it did not work. This is because the code for enabling and disabling the component happens within a frame, even though it works when I disable and enable it at runtime. This is because it happens with a frame delay, so it works when doing it at runtime. So I created a coroutine to re-enable the Vertical Layout component within 0.001 seconds; with this time frame, it will not be noticeable that it has a delay.
if(gameObject.name == "FireFacts")
{
transform.GetComponent<VerticalLayoutGroup>().enabled = false;
MG_ArticleTemplate = transform.GetChild(0).gameObject;
if (!(gameData.mgArticlesList == null))
{
for (int i = 0; i < gameData.mgArticlesList.Count; i++)
{
g = Instantiate(MG_ArticleTemplate, transform);
g.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = gameData.getMG_Article(gameData.mgArticlesList[i]).title;
g.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = "Published by <link=publisher><color=blue><u><b><font=\"Fredoka-Bold SDF\">" +
gameData.getMG_Publisher(gameData.mgArticlesList[i]).name + "</font></b></u></color></link> on <font=\"Fredoka-Bold SDF\">" +
gameData.getMG_Article(gameData.mgArticlesList[i]).date + "</font>";
g.transform.GetChild(3).GetComponent<TextMeshProUGUI>().text = gameData.getMG_Article(gameData.mgArticlesList[i]).description;
g.SetActive(true);
}
}
StartCoroutine(refresh());
}
private IEnumerator refresh()
{
yield return new WaitForSeconds(0.001f);
transform.GetComponent<VerticalLayoutGroup>().enabled = true;
}

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.

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.

How to make monster move left then right continuously C# XNA

i'm making my first game on XNA for my class. I'm trying to make the monsters move left and right automatically. I have total 4 monsters for now. I'm trying to get them move left then right within the screen.
//Monster movements
for (int i = 0; i < numOfMonster; i++)
{
if (destinationMonster[i].X >= screenWidth - 60)
{
while(destinationMonster[i].X != -10)
moveLeft = true;
}
else
{
moveRight = true;
}
if (moveLeft)
{
int temp = destinationMonster[i].X;
temp = destinationMonster[i].X - monsterSpeed;
//This prevents the object passing the screen boundary
if (!(temp < -10))
{
destinationMonster[i].X = temp;
}
moveLeft = false;
}
if (moveRight)
{
int temp = destinationMonster[i].X;
temp = destinationMonster[i].X + monsterSpeed;
//This prevents the object passing the screen boundary
if (!(temp > screenWidth - 50))
{
destinationMonster[i].X = temp;
}
moveRight = false;
}
}
Your first problem is your while statement, once you enter it you are not going to exit because you are not changing your X value. If it were me I would have a bool array variable corresponding to each of your monsters. I would also change your conditional to trigger the change of the boolean value once the monster has reached the extents at either end. Something like this.
if (destinationMonster[i].X >= screenWidth - 60)
{
moveRight[i] = false ;
}
else if (destinationMonster[i].X <= -10)
{
moveRight[i] = true ;
}

Categories