selecting blocks on mouse click
I have a 2.5d type game, with falling blocks (like tetris) and orthographic projection setup (I've setup my game as "3D" type).
I've defined a block like this:
public class Block{
public Block () {
this.gameObj = GameObject.CreatePrimitive (PrimitiveType.Cube);
}
public GameObject gameObj;
}
I have a BoardMgr (GameObj + script only component), where I spawn these blocks and store them in an array:
public class BoardMgr : MonoBehaviour {
protected Block[] blocks;
protected Block[,] board;
}
In BoardMgr::update()
, blocks are falling down one after the other (like tetris). Now, I'd like to figure out when I click on a block, which block object is it. This is the click detection code:
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
Debug.Log ("Ray hit block");
// How do I find which block got hit here ?
} else {
Debug.Log ("Ray missed block");
}
}
When I click on a block, I do see the ray hit block
on console, but then, how do I access which "Block" object got hit ? From RayCastHit, hit object, how do I decode which Block does it reference ?
I'm new to unity (2 days old) but not new to gamedev. Trying to find my way through unity here. I'd appreciate if someone can point me in the right direction here.
Look at the docs for RaycastHit.
hit.transform.gameObject.name
, probably, to find the block name.
You can access the transform from the RaycastHit. That's good enough. But the gameObject itself can be accessed from the transform, as Ive done above.
Should I change my block class definition ? I encapsulate gameobject in block. I can get a reference to the gameobject, but then I have no way to get a reference to the block object.
Answer by brainydexter · Apr 12, 2016 at 01:19 PM
I ended up instantiating all the blocks at Awake()
and store them in a dictionary indexed by getInstanceId()
. When I select an object, I index into the dictionary like this hit.transform.gameObject.GetInstanceID ()
. Saves me from looping :)
I have multiple clicks happening and lot of objects. If I end up looping for all of them checking for object, it would slow down! O(n) vs O(1)
Answer by ShadoX · Apr 04, 2016 at 09:05 AM
http://docs.unity3d.com/ScriptReference/RaycastHit.html
or simply put.. try something like:
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
Debug("Ray hit " + hit.collider);
} else {
Debug.Log ("Ray missed block");
}
}
@ShadoX I am already doing this. I need to figure out which block got hit and since block encapsulates gameObject, I don't know which block is it.
I'm guessing that you want to find which block inside the array was hit rather than which block was hit as you already know that but were asking:
I'd like to figure out when I click on a block, which block object is it
You could try having a look at http://docs.unity3d.com/ScriptReference/Object.GetInstanceID.html though I'm not sure if the IDs might not end up being the same. You'd have to look into that yourself. Or you could keep track of how many blocks you have and change up their name attribute when creating them and updating it to something that makes more sense, like "block_xx" with XX being the nr of it and then just go through the block array to find the index of it, though doing that might be a bit costly.
You could also just have a variable on a script on the bock itself that keeps track of the index of it in the array, but I'm guessing that the index can change at any time ?