- Home /
Raycasting around a gameObject while it's rotating
Hello, I have a gameObject that is a rectangle and im raycasting around it to check if it hits something. It works great when the object has 0 rotation. As soon as the rotation changes then the raycasts dont work because the math involed to calculate the raycasting spots are wrong. I was wondering if there is a way to rotate the gameObject after the raycasts have been set, so I can get the effect that I want.
The gameObject is inside a Canvas so im working in 2D screen space.
Any help would be much appreciated!
The code in C# that I use:
public bool RaycastCheck()
{
var size =
new Vector2(_collider.size.x * Mathf.Abs(transform.localScale.x),
_collider.size.y * Mathf.Abs(transform.localScale.y)) / 2;
var center = new Vector2(_collider.center.x * transform.localScale.x, _collider.center.y * transform.localScale.y);
Vector3 _raycastTopLeft = transform.position + new Vector3(center.x - size.x, center.y + size.y);
Vector3 _raycastBottomRight = transform.position + new Vector3(center.x + size.x, center.y - size.y);
Vector3 _raycastBottomLeft = transform.position + new Vector3(center.x - size.x, center.y - size.y);
Debug.Log("topleft"+_raycastTopLeft);
Debug.Log("bottomleft" + _raycastBottomLeft);
Debug.Log("bottomeright" + _raycastBottomRight);
float verticalDistaceBetweenRays = (_collider.size.x * Mathf.Abs(transform.localScale.x)) / 9;
float horizontalDistanceBetweenRays = (_collider.size.y * Mathf.Abs(transform.localScale.y)) / 3;
Vector2 transformUp = GetComponent<RectTransform>().rotation * Vector2.up;
Vector2 transformDown = GetComponent<RectTransform>().rotation * -Vector2.up;
Vector2 transformRight = GetComponent<RectTransform>().rotation * Vector2.right;
Vector2 transformLeft = GetComponent<RectTransform>().rotation * -Vector2.right;
for (int i = 0; i < 10; i++)
{
var rayVector = new Vector2(_raycastTopLeft.x + (i * verticalDistaceBetweenRays), _raycastTopLeft.y);
var rayVector1 = new Vector2(_raycastBottomLeft.x + (i * verticalDistaceBetweenRays), _raycastBottomLeft.y);
Debug.DrawRay(rayVector, transformUp * 3.5f, Color.red);
Debug.DrawRay(rayVector1, transformDown * 3.5f, Color.red);
var rayCastHit = Physics2D.Raycast(rayVector, transformUp, 3.5f);
var rayCastHit1 = Physics2D.Raycast(rayVector1, transformDown, 3.5f);
if (rayCastHit || rayCastHit1)
{
//Debug.Log("HIT");
return false;
}
}
for (int i = 0; i < 4; i++)
{
var rayVector = new Vector2(_raycastBottomLeft.x, _raycastBottomLeft.y + (i * horizontalDistanceBetweenRays));
var rayVector1 = new Vector2(_raycastBottomRight.x, _raycastBottomRight.y + (i * horizontalDistanceBetweenRays));
Debug.DrawRay(rayVector, transformLeft * 3.5f, Color.red);
Debug.DrawRay(rayVector1, transformRight * 3.5f, Color.red);
var rayCastHit = Physics2D.Raycast(rayVector, transformLeft, 3.5f);
var rayCastHit1 = Physics2D.Raycast(rayVector1, transformRight, 3.5f);
if ((rayCastHit.collider != null) || (rayCastHit1.collider != null))
{
//Debug.Log("HIT");
return false;
}
}
return true;
}
Here is a visualization of what I want:
Answer by robertbu · Oct 16, 2014 at 02:08 AM
My usual solution for this problem is to use local coordinates. So for each ray, you would specify a local position and a local direction. The local forward of an object is always Vector3.forward. The center of the object is always Vector3.zero. Local coordinates are always calculated based on a local scale of (1,1,1). The front, left, top corner of a cube has a local coordinate of (-.5, .5, .5) regardless of the size, position, or rotation of the cube.
For the number of raycasts you are doing, consider using an array.
Then when you do the Raycast(), you can do:
var rayCastHit = Physics2D.Raycast(transform.TransformPoint(localPosition), transform.TransformDirection(localDirection), 3.5f);
The Transform.TransformPoint() call and Transform.TransformDirection() call take the local position and direction and transforms them into world space...it takes into account changes in position, rotation and scale.
Hey @robertbu, thanks for your answer! I tried to use the local coordinates as you said, but when I use the transform.TranformPoint() method all I get is a small square raycasting around it inside my rectangle object. The Unity Scripting Reference says that "Note that the returned position is affected by scale.", so I think maybe this is a scaling problem. $$anonymous$$aybe I have to multiply something with height and width of the object??
Any ideas how to fix that??
Code so far for the Top and Bottom Raycasts:
public bool RaycastCheck()
{
var size = new Vector2($$anonymous$$athf.Abs(transform.localScale.x),$$anonymous$$athf.Abs(transform.localScale.y)) / 2;
var center = Vector3.zero;
Vector3 _raycastTopLeft = new Vector3(center.x - size.x, center.y + size.y);
Vector3 _raycastBottomRight = new Vector3(center.x + size.x, center.y - size.y);
Vector3 _raycastBottomLeft = new Vector3(center.x - size.x, center.y - size.y);
float verticalDistaceBetweenRays = $$anonymous$$athf.Abs(transform.localScale.x) / 9;
float horizontalDistanceBetweenRays = $$anonymous$$athf.Abs(transform.localScale.y) / 3;
Vector2 transformUp = transform.up;
Vector2 transformDown = -transform.up;
Vector2 transformRight = transform.right;
Vector2 transformLeft = -transform.right;
Vector2[] rayVector = new Vector2[10];
Vector2[] rayVector1 = new Vector2[10];
for (int i = 0; i < 10; i++)
{
rayVector[i] = new Vector2(_raycastTopLeft.x + (i*verticalDistaceBetweenRays), _raycastTopLeft.y);
rayVector1[i] = new Vector2(_raycastBottomLeft.x + (i*verticalDistaceBetweenRays), _raycastBottomLeft.y);
}
foreach (Vector2 vector in rayVector)
{
Debug.DrawRay(transform.TransformPoint(vector), transform.TransformDirection(transformUp) * 3.5f, Color.red);
var rayCastHit = Physics2D.Raycast(transform.TransformPoint(vector), transform.TransformDirection(transformUp), 3.5f);
if (rayCastHit.collider != null)
{
//Debug.Log("HIT");
//return false;
}
}
foreach (Vector2 vector in rayVector1)
{
Debug.DrawRay(transform.TransformPoint(vector), transform.TransformDirection(transformDown) * 3.5f, Color.red);
var rayCastHit1 = Physics2D.Raycast(transform.TransformPoint(vector), transform.TransformDirection(transformDown), 3.5f);
if (rayCastHit1.collider != null)
{
//Debug.Log("HIT");
//return false;
}
}
}
You are using world directions not local directions. Change to:
Vector2 transformUp = Vector3.up;
Vector2 transformDown = Vector3.down;
Vector2 transformRight = Vector3.right;
Vector2 transformLeft = Vector3.left;
Or alternately you can not call transform.TranformDirection().
This:
transform.TransformDirection(Vector3.forward);
is the same as:
transform.forward;
As for your positions, calculate the values based on a rotation of (0,0,0), position of (0,0,0), and scale of (1,1,1).
@robertbu I changed the local directions and they seem to work great with the object's rotation but the raycasts still dont scale up around the edges of the rectangle but stay in middle. $$anonymous$$aybe its because I use unity 4.6 beta and the object is inside a Canvas so the world coordinates are different? $$anonymous$$aybe because it has a Rect Transform component and not a Transform?
Your answer
Follow this Question
Related Questions
Input problem 1 Answer
Physics based rigidbody rotation with a constant force 1 Answer
Pysics not working as expected 1 Answer
wasd movement rigidbody no bouncing 0 Answers