Raycast issues while rotating a GameObject

My game has a stack of tiles. They are all child objects of the board. Tiles are “Selectable” based on whether they have neighbors to the left/right/up. I am using a raycast to determine if there is another tile in those directions.

I added a simple script on the board so that it can be rotated around the X-axis.

public float rotateSpeed = 20;
public void OnMouseDrag() {
     float rotateX = Input.GetAxis("Mouse X") * rotateSpeed * Mathf.Deg2Rad;
     transform.Rotate(Vector3.up, -rotateX);
}

My raycast script looks like this and is attached to the tile prefab (these become the child objects of the object being rotated).

IsBlockedLeft = Physics.Raycast(transform.position, Vector3.right, .9f);
IsBlockedRight = Physics.Raycast(transform.position, Vector3.left, .9f);
IsBlockedUp = Physics.Raycast(transform.position, Vector3.up, .5f);

Before I added the rotation, my raycasts were slightly different, but in experimenting this morning I have found that there is no functional difference in the way they are now and the way they were. I had them like this

IsBlockedLeft = Physics.Raycast(transform.position, transform.TransformDirection(Vector3.right), .9f);
IsBlockedRight = Physics.Raycast(transform.position, transform.TransformDirection(Vector3.left), .9f);
IsBlockedUp = Physics.Raycast(transform.position, transform.TransformDirection(Vector3.up), .5f);  

The raycast vector values are based upon the size of the tiles. They are cubes with a size of 0.75, 0.3, 1, so the vector is just supposed to go to the center of the next cube. I’m not sure why the left/right reversal works, neither the parent nor the tiles have any rotation on them. But, it is detecting neighboring tiles correctly this way.

The raycast is working perfectly until I start rotating the board and then they all go haywire and either start hitting things when there is not another tile there, or stop hitting the ones that are there. I know this because the “IsBlocked” values are public bools that I can see in the inspector and the tiles also change color as those values change. So as I start to rotate the board, I can see them changing. I suspect that it has something to do with needing to adjust the raycast vector based on the rotation, but I haven’t been able to find a way to do this correctly.

It’s probably also important to note that when I’m rotating the board (the parent object) if you watch the tiles (child objects) in the inspector the position, rotation, and scale all remain unchanged, only the parent’s transform values change.

To try and confirm my suspicions, I had the debugger draw all 3 rays. You can see in this image how the angle they are going changes with the rotation of the board. Before the rotation, the left and right rays were going straight out from the center, as they are supposed to do.

Any insights/suggestions etc… would be greatly appreciated.

So, I finally found a solution to this issue. However, if anyone else has any ideas, I would still like to hear them. I’m not very experienced with Unity, so I would like to see if I solved it the way more experienced Unity developers would have…

I figured out that the problem wasn’t that the rays were rotating with the board, it’s that they WEREN’T rotating with the board. So, as the board and all the child objects (tiles) rotated, the rays were still being cast in their original direction. Here was my solution, there were 3 parts to it:

First, I changed the direction of my rays to be based on the board’s transform instead of the tile’s transform and adjusted their length slightly. The Code now looks like this:

Ray leftRay = new Ray(transform.position, transform.parent.TransformVector(Vector3.left));
Ray rightRay = new Ray(transform.position, transform.parent.TransformVector(Vector3.right));
Ray upRay = new Ray(transform.position, transform.parent.TransformVector(Vector3.up));

IsBlockedLeft = Physics.Raycast(leftRay, .6f);
IsBlockedRight = Physics.Raycast(rightRay, .6f);
IsBlockedUp = Physics.Raycast(upRay, .4f);

Second, I added an “IsRotating” bool to the board. And control it in OnMouseDrag() and OnMouseUp().

public void OnMouseDrag() {
   IsRotating = true;
   float rotateX = Input.GetAxis("Mouse X") * rotateSpeed * Mathf.Deg2Rad;
   transform.Rotate(Vector3.up, -rotateX);
}
public void OnMouseUp() {
     IsRotating = false;
}

And finally, I increased the size of the box collider on the tiles to 1.25/1.25/1.25. I had to do this because on the ends of some of the rows of tiles, there are ones that are offset and cover the ends of two rows. The tiles behind these were still experiencing a little bit of a problem of missing the tile that was only covering half of their left or right side. But, increasing the size of the collider solved this and testing hasn’t shown any other issues arising from that so far.