Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

When our game's ships move around, mouse aiming causes them to shake around a lot. The body being aimed is moved kinematically. I think we've narrowed it down to this block of mouse tracking code.

Demonstration of the glitch

You can see around 0:35 where I disable the mouse tracking code momentarily, the ship stops shaking.

    public static Quaternion RotateToMouse(this Ship ship, Transform transform, float ShipRotateSpeed)
    {
        // Generate a plane that intersects the transform's position with an upwards normal.
        Plane playerPlane = new Plane(Vector3.up, Vector3.zero);

        // Generate a ray from the cursor position
        Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);

        // Determine the point where the cursor ray intersects the plane.
        float hitdist = 0.0f;
        // If the ray is parallel to the plane, Raycast will return false.
        if (playerPlane.Raycast (ray, out hitdist)) 
        {
            // Get the point along the ray that hits the calculated distance.
            Vector3 targetPoint = ray.GetPoint(hitdist);

            // Determine the target rotation.  This is the rotation if the transform looks at the target point.
            Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position);


            // Smoothly rotate towards the target point.
            transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, ShipRotateSpeed);
            transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
        }
        return transform.rotation;
    }

We've got no idea whats going wrong, any help will be greatly appreciated. thanks.

share|improve this question
    
I don't have much time to write a formal answer (and think it through enough to warrant a formal answer) but, instead of Quaternion.RotateTowards(), you likely want Quaternion.Slerp() (link) to ensure you don't overshoot your target rotation. –  chaosTechnician May 2 '13 at 18:56
    
Using quaternions for a rotation in a plane seems a bit overkill, and probably helps to obscure the bug. That said, this code as best I can tell is functionally correct. @chaosTechnician Nope, RotateTowards should not overshoot according to the specification, Slerp produce a different effect that I presume undesirable for the purpose. –  eBusiness May 2 '13 at 19:09
    
As eBusiness said, using quaternions here is weird. Some things to check: Is targetPoint.y always exactly zero? Is transform.position.y always exactly zero? If not, then Quaternion.LookRotation will produce a rotation that is not exactly about the y axis. Also, Unity documentation considers Quaternion.RotateTowards to be "only for exotic uses", so maybe the function just isn't very robust(docs.unity3d.com/Documentation/ScriptReference/Quaternion.html). –  Eric Undersander May 3 '13 at 15:43
add comment

1 Answer 1

up vote 1 down vote accepted

Something i forgot to include was the fact the camera was moving with the ships. When I made the Camera stationary it seamed to work perfectly, so i simply created another camera and kept it at Vector3(0,30,0) and used it to track the mouse instead.

Changing the code slightly to be:

    public static Quaternion RotateToMouse(this Ship ship, Transform transform, float ShipRotateSpeed)
    {
        Vector3 MousePos = Input.mousePosition;

        // Generate a plane that intersects the transform's position with an upwards normal.
        Plane playerPlane = new Plane(Vector3.up, Vector3.zero);

        // Generate a ray from the cursor position

        Ray ray = Vitals.MouseCam.ScreenPointToRay (MousePos);


        // Determine the point where the cursor ray intersects the plane.
        float hitdist = 0.0f;
        // If the ray is parallel to the plane, Raycast will return false.
        if (playerPlane.Raycast (ray, out hitdist)) 
        {       
            // Get the point along the ray that hits the calculated distance.
            Vector3 targetPoint = ray.GetPoint(hitdist);
            targetPoint += transform.position;
            // Determine the target rotation.  This is the rotation if the transform looks at the target point.
            Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position);

            // Smoothly rotate towards the target point.
            transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, ShipRotateSpeed);
        }           
        return transform.rotation;
    }

Something about the Camera moving caused the calculations to be slightly different every tick? Ideas ?

share|improve this answer
    
My guess is that it's an order issue. Maybe whatever is moving the ship is doing that before the camera or vice-versa. Try moving some code from Update to LateUpdate in one script or another and see if it helps things. –  Tetrad May 17 '13 at 22:32
    
@Tetrad That was my guess as well, I did move the camera movement code around but it didn't seem to help. It may have just have ended up with slightly different angles because of the positions. –  Dusty May 18 '13 at 12:14
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.