- Home /
Finding a GameObject by transform.position
is there a way to find a gameobject by their position? I want to use it for placing blocks so that you can't place blocks evrywhere and i want to use that to find the 4 possible gameobject(2d game) around the block you want to place. If you know another way to fix my problem tell me. btw you don't have to type a full script just tell me what to do (C#)
Answer by ElijahShadbolt · Nov 09, 2016 at 06:59 PM
You could store each GameObject block in a 3D array, where its index corresponds to its transform's position.
For example, you could make a Block component with the fields int x, y, z;
, and attach the script to each block. Another script, BlockController, would hold a 3D array of blocks, eg Block[,,] blocks
, and a static Vector3 size;
for the dimensions of each block.
Then on Awake() you could set the position of the block to the index multiplied (scaled) by the block size, like so: new Vector3(x * size.x, y * size.y, z * size.z)
, and also add the Block to the BlockController's blocks
array via its index like so: blocks[x,y,z] = Block;
Then to get the closest block to a point, you would divide (inverse scale) the point by size
and round each x,y,z component to an integer, to get its index in the blocks
array.
This would definitely also work. $$anonymous$$aybe a bit simpler if one is not comfortable with dictionaries and such :)
I have just realised that this only applies to positive coordinates. A 3D array can only use index integers that are >= 0, so if any index component (i.e. x, y, or z) is negative, it cannot store a value in that index in the array. You could overcome this problem by taking the block's world position (after inverse scaling) and subtracting it by a $$anonymous$$imum value that is smaller than zero. That means the normalised world coordinates are >= 0, and then you can round it to an integer.
Answer by Mikael-H · Nov 09, 2016 at 06:55 PM
There are several ways to do this.
If your positions are discrete and only one object should occupy every position then you could create a unique identifier for each position and use as key in a dictionary:
const int width = 16;
Dictionary<int, GameObject> objects = new Dictionary<int, GameObject>();
int GetKey(int x, int y) {
return x + width * y;
}
int GetXFromKey(int key) {
return key % width;
}
int GetYFromKey(int key) {
return key / width;
}
public GameObject GetGameObjectAtPosition(int x, int y) {
int key = GetKey(x, y);
if (objects.ContainsKey(key))
return objects[key];
else
return null;
}
public bool TryInstantiatePrefabAtPosition(int x, int y, GameObject prefab) {
int key = GetKey(x, y);
if (objects.ContainsKey(key))
return false;
var obj = Instantiate<GameObject>(prefab);
obj.transform.position = new Vector2(x,y);
InsertGameObjectAtPosition(x,y,obj);
return true;
}
public void InsertGameObjectAtPosition(int x, int y, GameObject obj) {
int key = GetKey(x, y);
if (objects.ContainsKey(key))
throw new System.Exception("Nope, position already taken...");
else
objects[key] = obj;
}
I haven't tested the code, just wrote from memory from a similar solution I've used before so there could be some spelling errors. Let me know if it works!
If this solution does not apply then I would recommend using 2d raycast, 3d raycast or any of the other available casts available in the physics libraries
Edit: Changed the code to contain an instantiate. Call TryInstantiatePrefabAtPosition and it will return true if the object was instantiated and false otherwise.
i have no idea what stands here can you just tell where i need to put my Instantiate so whats tells now if there is a block next to it or not
Ahh, ok, hold on, will add that as well to the code...
and to use dictionary i think i need a new using type like now i only use UnityEngine;
like you saw yourself the otherone was much easier i figured that out. and in you code i got like 30 errors of { adn [ that you forgot
This is not the entire class, this is intended to go inside your class definition... Glad it worked out for you though
Answer by salamander555 · Nov 10, 2016 at 05:58 PM
@Mikael-H @SublimeGamer hey i hoped one yo you could help me out one more time. I can only palce blocks when there is anothe block next to it, this is normal. but once i get to a specific height. i can't place blocks anymore i know where the problem is but i have no idea how to fix it.
so how my script works is in my first script evrythime a block is created its location will be add to a list
now when i press right click to place a block it will check for this all will happen with some more bools but that's not the problem more explained below
// this fix some collision bugs
mousePosition = new Vector2(Mathf.Round(mouse.x * 2f) * 0.5f, Mathf.RoundToInt(mouse.y * 2f) * 0.5f);
if (!coords.Contains(mousePosition))
{
// what happens here i take the rounded postion of the mouse and I make
//the 4 sides where the block can be placed against (north = above,...)
//but ONCE that the Y position of one of these variables is greater than 0
//it doesnt work anymore So the NextTo varibale doesn't turn true
north = new Vector2(mousePosition.x, mousePosition.y + 0.5f);
south = new Vector2(mousePosition.x, mousePosition.y - 0.5f);
east = new Vector2(mousePosition.x + 0.5f, mousePosition.y);
west = new Vector2(mousePosition.x - 0.5f, mousePosition.y);
if (coords.Contains(north)|| coords.Contains(east) || coords.Contains(west) || coords.Contains(south))
{
//THE ABOVE IF STATEMENT DOESNT TRIGGER WHEN IT'S SUPPOSED TO TRIGGER i checked it
test = true;
nextTo = true;
}
i have no idea why that once the Y (of one of the 4 variable) is greater than zero that it doesnt work anymore if you need some more information juts ask
Why are you checking for Vector2's in (what seems to be) a list? If it is off by even the slightest amount due to rounding errors, the list might think they are completely different, so List.Contains() will return false.
I would make my own 'int2' class in place of the Vector2's, and just convert the coordinates from being a Vector2 in world space to an int2 with the rounded values, and then check it against other int2's in the coords list.
First of all, you posted this as an answer. This is either a new question (you can tag other users in new questions as well, just as you did here) or an edit to your original question.
That being said, I agree with @SublimeGamer that you chould probably make your or "int2"-class.
Now, regarding the question at hand, is it onlyy the last block that does not trigger? Have you tried putting breakpoints and just step through the code, monitoring, all variables? That's how I would solve this problem.