- Home /
2d rotation and translation issue
I am stuck in this weird issue .
First I want that my instantiated object should always translate in the direction of its head but it should be a random direction.
Second ,
I want this translation object to bounce off any object it collides with like this .
Script done so far :
Vector3 directionOfMovement = Vector3.zero;
public bool shouldTranslate = false;
void Start()
{
SetDirection();
Invoke("StartTranslating", 1);
}
void SetDirection()
{
float x = Random.value;
float y = Random.value;
directionOfMovement = new Vector3(x, y, 0);
directionOfMovement = directionOfMovement.normalized;
}
void StartTranslating()
{
shouldTranslate = true;
}
void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag == "Wall" )
{
Vector3 direct = Vector3.Reflect(directionOfMovement, other.contacts[0].normal);
directionOfMovement = direct;
directionOfMovement = directionOfMovement.normalized;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0, 0, -transform.rotation.z), 1);
}
}
void FixedUpdate()
{
transform.Translate(directionOfMovement * speed * Time.deltaTime);
}
$$anonymous$$udos for including a diagram, but it's not clear what your question is. For best results, always include a brief but thorough description of your scene, what's happening, what you want to have happen ins$$anonymous$$d, and trim your code to exclude unnecessary lines.
ok...
So what I want is :
Lets say this triangle is my player which gets instantiated in scene at runtime at a random rotation of angle along z-axis.Now i want to translate it only in the direction ,its head(tip) is pointed (the one mentioned in "1.png" above and not in some random direction.
now as this object is translating ..it will collide with the walls.. So what i want is ...collision should occur with wall and then this object gets reflected off the wall as shown above in "2.png". the issue is reflection works fine but the initial rotation of this object remains same. the player should rotate itself so that its tip point now is reversed along the new reflected direction. unable to rotate object after collision properly ...
Hope i am clear this time... (P.S. its an 2d game in xy plane.)
Answer by robertbu · Aug 28, 2014 at 06:11 PM
The question is clearer but I'm still puzzled. You state this is a 2D game, but you are using OnCollisionEnter() so it indicates you have a 3D collider on your object. Given a triangle shape to your object, this indicates a custom mesh?
I guess the last ingredient needed is what side of your object do you consider the front side when the rotation is (0,0,0)? For 3D rotations typically you want the mesh constructed so that when the rotation is (0,0,0), the front side is facing positive 'z' and the top side is facing positive 'y'. If this is the case, you likely want this as the destination rotation for your Quaternion.Slerp():
Quaternion qTo = Quaternion.LookRotation(directionOfMovement, Vector3.forward);
If the right side is considered front (as is typical of sprites), then you likely want:
float angle = Mathf.Atan2(directionOfMovement.y, directionOfMovement.x) * Mathf.Rad2Deg;
Quaternion qTo = Quaternion.AngleAxis(angle, Vector3.forward);
@robertbu actually its an 2d game but i made use of 3d features because i guess we dont have vector3.reflect in 2d... how to make this entire thing work by using only 2d features...i mean translating in particular direction then getting reflected on hitting with wall by rotating itself at required angle for rotation???
this is my world coordinates gizmo...
Y
^
|
|
X <--- o
camera transform : pos = vector3(0,0,10); rot = vector3(0,180,0);
First, if positive 'x' is to the left as indicated by your text drawing, you've set things up in a strange way. Typically for 2D, the camera is setup pointing towards positive 'z' with rotation (0,0,0), which makes positive 'x' to the right.
Second I have no particular issue with using 3D colliders in a 2D game other than you have to make sure you preserve the 'z' position and zero out out 'z' velocity. That is, it is possible with a Physics.Rigidbody() to hit some mesh in such a way that the velocity has a 'z' component, so you need to put some code in FixedUpdate() to take care of that potential situation.
Or if you do a 2D app with 2D colliders, you can cast to 3D, do the Vector3.Reflect, and cast back to 2D. Or if you really want a 2D Reflect, here is a method you can add:
static Vector2 Reflect(Vector2 inDirection, Vector2 inNormal) {
return 2.0f * Vector2.Dot (inDirection, inNormal) * inNormal - inDirection;
}
As long as your object is setup in one of the two ways I describe above, the rotation code will work to face your object in the new direction.
@robertbu its all getting very confusing for me man ... a bit more help from your side... can you write me a clean code for taking 2d into consideration (physics 2d) because 3d is giving me weird results on collision .can i make this all work with only script, no physics involved..if yes what all will i have to do ... and what shall be the camera settings in order to get desired results....
I'd probably do it with Physics2D. But if I wasn't doing it with Physics, here is how I might approach the problem:
using UnityEngine;
using System.Collections;
public class Player : $$anonymous$$onoBehaviour {
public float speed = 1.5f;
public float rotateSpeed = 180.0f;
private Vector3 direction;
private Quaternion qTo;
void Start () {
direction = Quaternion.AngleAxis(Random.Range (0.0f, 360.0f), Vector3.forward) * Vector3.right;
float angle = $$anonymous$$athf.Atan2 (direction.y, direction.x) * $$anonymous$$athf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis (angle, Vector3.forward);
qTo = transform.rotation;
}
void FixedUpdate () {
Vector3 pos = transform.position + direction * speed * Time.fixedDeltaTime;
rigidbody2D.$$anonymous$$ovePosition (pos);
float angle = $$anonymous$$athf.Atan2 (direction.y, direction.x) * $$anonymous$$athf.Rad2Deg;
qTo = Quaternion.AngleAxis (angle, Vector3.forward);
transform.rotation = Quaternion.RotateTowards (transform.rotation, qTo, rotateSpeed * Time.fixedDeltaTime);
}
void OnTriggerEnter2D(Collider2D col) {
collider2D.enabled = false;
RaycastHit2D hit = Physics2D.Raycast (transform.position, direction);
collider2D.enabled = true;
Debug.DrawRay (transform.position, direction, Color.red, 1.0f);
Debug.DrawRay (hit.point, hit.normal, Color.green, 1.0f);
if (hit.collider != null) {
direction = (Vector2)Vector3.Reflect((Vector3)direction, hit.normal);
}
}
}
You will find a Unity package at:
www.laughingloops.com/TriBounce.unitypackage
It is not a perfect solution since oblique angles will produce 'extra' hits. You could probably reduce that problem by putting a Circle2D collider right at the tip of the triangle and removing the Polygon2D collider.
Edit: Yep, a small circle collider just at the tip of the triangle produces much better results than the pollygon collider.
As for $$anonymous$$ovePosition(), you need to update your version of Unity. Rigidbody2D.$$anonymous$$ovePosition() was not in the first versions of the 2D release. It was added in a later release. So Download and install Unity3d 4.5.3
I updated the package at the line above to have the version with the circle collider. It works fine for me, though you'll notice at certain oblique angles, parts of the triangle can be outside the the lines since there is only a collider at the tip.