- Home /
2D lock x,y rotation to look at target
Hi. Making a 2D top down space shooter (think asteroids) using sprites as ships. I'm having huge trouble getting npc ships to look at their target and not disappear. I've had success using 'LookAt' and then correcting the rotation but this method means that whenever an npc changes its target, it snaps directly to looking at the next one, which looks bad. I need them to turn gradually, or at least to dampen the LookAt funciton. It should only rotate on the Z axis, or else it disappears since it's a 2D sprite.
There's a huge amount of threads on this and believe me, I've probably read them all at this stage, so please don't link me to more of them without having a gander at the code I'm using below to see if you can fix something or recommend a different method entirely.
private GameObject player;
public float rotatespeed = 2;
public float damping = 10;
private Quaternion rotation;
float MaxClamp = 0.0f;
float MinClamp = 0.0f;
private Quaternion Rotation;
void Awake()
{
player = GameObject.FindGameObjectWithTag ("Player");
Rotation = transform.rotation;
}
void FixedUpdate()
{
rotation = Quaternion.LookRotation (player.transform.position - transform.position, Vector3.forward);
transform.rotation = Quaternion.Lerp (transform.rotation, rotation, Time.deltaTime * rotatespeed/damping);
transform.Rotate(new Vector3(0,-90,-90),Space.Self);
//correcting the original rotation
//can't get the ship to orient itself correctly
}
void LateUpdate()
{
Rotation.eulerAngles = new Vector3(
Mathf.Clamp (transform.rotation.eulerAngles.x, MinClamp, MaxClamp),
Mathf.Clamp (transform.rotation.eulerAngles.y, MinClamp, MaxClamp),
transform.rotation.eulerAngles.z);
//DIDN'T WORK
}
I've commented in/out several parts of this to see what I could get. The Late Update part doesn't seem to do anything at all, though I believe it's the most correct way to orient my 2d sprite. The behaviour I get from the first part of Update is that the sprite rotates to point its broad side (the visible side) towards the player, therefore I can't see it anymore from the camera position. I've tried all combinations of telling it the 'World Up' in the function (forward, up, right, and negatives of those) but it always rotates to be invisible from the camera.
The second part of update, if I leave it in, causes the ship to basically flip out; rotating around all axes constantly so it looks like a blurry, pointy mess. This is odd because it's the exact same line of code I was using to correct my LookAt rotation when I was using that before, and it worked then, except for the 'snapping' to a new target that I mentioned at the top.
Sorry for the length, but I just want to get across what's happening. I need very specific help, as I feel I've been through every search result on the topic and tried every aspect of every suggestion on those other pages. I thought it best to get my specific problem detailed here.
Thanks if you've read this far :P
Answer by robertbu · Oct 09, 2014 at 08:31 PM
I've posted the 2D LookAt a number of times, but here it is again. Assumes:
Standard setup of action on the XY plane with the camera looking towards positive 'z'.
That the front side of the sprite is the right side.
Vector3 dir = player.transform.position - transform.position; float angle = Mathf.Atan2(dir.y, dir.x) Mathf.Rad2Deg; Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward); transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime speed);
Note that by using Slerp, you will get an eased rotation. If you don't want eased, change Slerp() to RotateTowards() and increase 'speed' (will be degrees per second).
Thanks a mil. 4 lines of code that work perfectly. You've no idea how long I've been held up trying to get this working. I'll have to look up what Atan2 is really doing, and I had to rotate my original sprite 90 degrees to match your code, as I couldn't see how to adjust the code itself to match a sprite with 'forward' at 12 o clock. But thanks so much. A solution that works!
You can use a sprite where 'up' is the front by adding 90.0 to 'angle' before passing it to AngleAxis().
Answer by saramul · Jun 06, 2016 at 07:12 AM
Vector3 dir = player.transform.position - transform.position Quaternion rotation = Quaternion.LookRotation(new Vector3(dir.x, 0, dir.z)); transform.rotation = rotation;