SETUP: a gridlayout of many gameobjects (GO’s) which only have an Image component and a script which keeps track of which variable state they are in(1-4), and changes their state based on the state of surrounding GO’s. (so think dead, alive, dead if too many dead around it)
Desire: To create a set reference of each “neighboring” object on the gridlayout. None of the objects move on the layout, so once a reference is set I’m all good. And from there when the objects need to check what is around them, I can just check the reference
Problem: I have no idea how to set a reference in this fashion. I would think just using the Vector3Int based on the parent’s GridLayout, but I dont know how to properly write
" gameobject above = this. vector3int +(0,1,0)"
any help translating this to code would be great, or advise on a better way to do this
If you know how many rows/columns your grid layout has, you can convert an object’s sibling index to its coordinates within the grid.
(Sort of. If your grid layout has any children with the “ignore layout” flag, that will throw this off.)
You’ll have to adjust this slightly depending on whether your grid lays out children in up/down/left/right order, but it would be something along the lines of:
// Assuming the grid order is going down rows first
// Calculate row/column based on sibling index
int row = siblingIndex / columnCount;
int column = siblingIndex % columnCount;
// Calculate index based on row + column
int sibIndex = row * columnCount + column;
With those formulas, you can convert an object’s sibling index into coordinates, calculate neighboring coordinates from those, and then convert the new coordinates back into a sibling index so that you can get a reference to the matching object.
When calculating offsets (e.g. going one cell to the right), you’ll need to explicitly check if you have hit the edge of the grid; that is, if column >= columnCount or if column < 0 etc. If you just plug the numbers into the math without checking, you’ll “wrap around” to the next row.
1 Like
Thank you much for the answer. What I would need to know now it how to declare a reference to the gameobject at that location.
Maybe a communication failure.
So when I say reference, I mean a local variable which is set at the gameobject.
Aka, when you declare a public gameobject, then set it in the inspector, that public gameobject is now a reference to the gameobject. Perhaps there’s a different term for this.
I can’t figure out what you’re trying to ask.
If you want to set a variable via the inspector, just make it a public field. (But you seem to already know how that works.)
If you want to obtain a reference through script to the game object at a specific coordinate in the grid, then I just told you how to do that. (Calculate its sibling index and then use GetChild.) The only additional step for turning that into a variable is to write myVariable = in front of it.
If all of your Gameobjects are at an equal distance from each other than you can set their neighbours like this:
- In the script you have on each GameObject:
public class Tile : MonoBehaviour
{
[Range(1, 4)]
public int state;
[HideInInspector]
public List<Tile> surroundingTiles = new List<Tile>();
// Call this method to deal damage to this tile
public void TakeDamage(int dmg)
{
dmg = state == 1 ? 0 : dmg;
if (dmg != 0)
{
foreach (Tile t in surroundingTiles)
t.TakeCollateralDamage(dmg%2 == 0 ? dmg/2 : 1);
}
}
// Called from the tile that took damage and sent damage to neighbours
public void TakeCollateralDamage(int dmg)
{
state -= state == 1 ? 0 : dmg;
}
}
the only thing you really need to do is add the surroundingTiles List to your script that is attached to each GameObject, the rest is just an example of what you could do with the surroundingTiles List.
Add all GameObject’s to the same parent object and add this script to the parent:
using System.Collections.Generic;
using UnityEngine;
// Add this class to the parent of the tiles
public class TileParent : MonoBehaviour
{
public float distanceBetweenTiles;
Tile tile;
Transform currentTile;
Transform otherTile;
private void Start()
{
SetReferences();
}
private void SetReferences()
{
for (int i = 0; i < transform.childCount; i++)
{
currentTile = transform.GetChild(i);
tile = currentTile.GetComponent<Tile>();
for (int j = 0; j < transform.childCount; j++)
{
otherTile = transform.GetChild(j);
// This will get all the tiles surrounding tile and add them to the tile's 'surroundingTiles' List
if (Mathf.Approximately(Vector3.Distance(currentTile.position, otherTile.position), distanceBetweenTiles))
{
tile.surroundingTiles.Add(otherTile.GetComponent<Tile>());
}
}
}
}
}
It will get all surrounding GameObjects of currentTile and puts them in its ‘surroundingTiles’ List.
Not sure but if your GameObjects are Canvas.UI.Image you’ll need to change the check for Transforms to a check for RectTransforms and look for their AnchoredPosition3D.
Hope this helps.
1 Like