Search Unity

Rotating to broadside gets stuck

Discussion in 'Scripting' started by KelsoMRK, May 22, 2015.

  1. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    So I'm creating a behavior where a unit will rotate in place so that one of its "broad sides" (ie a side perpendicular to forward) faces a target. I've got the calculation working
    Code (csharp):
    1.  
    2. Vector3 toTarget = target.transform.position - owner.transform.position;
    3. float angle = Vector3.Angle(passengerSlot.forward, toTarget);
    4. Quaternion rot = Quaternion.AngleAxis(angle, Vector3.up);
    5. Vector3 lookAt = rot * owner.transform.forward;
    6. Quaternion rotation = Quaternion.FromToRotation(owner.transform.forward, lookAt);
    7.  
    where passengerSlot is a child transform facing perpendicular to owner's forward. The idea is to rotate owner so passengerSlot faces target.

    If I do this
    Code (csharp):
    1.  
    2. owner.transform.rotation = rotation;
    3.  
    owner snaps to the correct rotation and it works fine.

    When I try to smooth it with
    Code (csharp):
    1.  
    2. owner.transform.rotation = Quaternion.RotateTowards(owner.transform.rotation, rotation, TurnRate * Time.deltaTime);
    3.  
    owner rotates a bit and then snaps back to more or less face the target directly and wobbles for the remainder of the state.
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    That's really strange — I would expect that to work.

    However, since your code already assumes that we're rotating around Vector3.up, you could dispense with quaternions with most of it and just treat your rotation as an angle. In that case it's quite easy: just find the forward angle to the target (with Mathf.Atan2), and then add or subtract 90 degrees to face to the side (presenting a "broadside"). Then you can use Mathf.MoveTowardsAngle to interpolate.

    The end result ought to be the same as what you're doing, but may be easier to debug since it's easy to inspect and interpret the intermediate values.

    HTH,
    - Joe
     
  3. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    In this instance rotating 90 degrees would work but because passengerSlot is a child transform that can change from unit type to unit type it might not always be 90 degrees.But that is an interesting approach, thanks.

    I'll go back through and see if something else is interfering with the execution of this block of code. As long as someone else looks at it and says "that *should* work" then I know my math was right and I've just made a stupid error somewhere else :)

    Edit: And it was a stupid error on my part. This runs in a specialized attack state and the base attack state was LookAt()'ing the target.Setting the rotation worked because it ran afterwards but trying to smooth it just rotated from the initial LookAt.
     
    Last edited: May 22, 2015
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Ah, cool, thanks for posting a follow-up. That totally makes sense now.
     
  5. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Hm - seems I was wrong about this working completely. In instances where owner is facing target head on (the required rotation amount should be nearly 90) it dips into the ground; rotating along it's Z axis and then spinning like a top to present its broadside.

    I'm guessing it's a funky Gimbal thing that's occurring from going from vector to quaternion.