Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Quaternion.Slerp not working as I think it should...

Discussion in 'Editor & General Support' started by The_Raz, May 21, 2014.

  1. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    here is my code, what I want it to do is rotate the object so the +Z is pointing towards the floor to create a parabolic shape of a projectile traveling. What I get is it seems to want to avoid certain directions and turns away from them... I simply want the projectile to rotate towards the floor as it travels.

    transform.localRotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(((transform.position + Vector3.down) - transform.position), transform.position), Time.deltaTime * drop);

    $Illustration.png


    And this is an example of what is occuring when I fire instead of it traveling straight and then dropping.
    It is a picture from above looking down at my 'character' firing. when facing 0,0,0 (which it is in this picture) the bullets split off and curve in a strange way to reach what is under it.

    $illustration 2.png
     
    Last edited: May 22, 2014
  2. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    Here is the rest of the code if it helps, I wish there was an easy button here. I just want the front end to tip downward in the direction its traveling which is always forward on the Z axis....

    Code (csharp):
    1.  
    2.  
    3. float Distance = speed*Time.deltaTime;
    4.         if(speed > stopspeed)
    5.         {
    6.             if(LockOn == true)
    7.             {
    8.                 transform.rotation = Quaternion.Slerp(transform.rotation, (Quaternion.LookRotation(Target.transform.position - transform.position)), Time.deltaTime * 2);
    9.             }
    10.             else
    11.             {
    12.                
    13.                 transform.localRotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(((transform.position + Vector3.down) - transform.position), transform.position), Time.deltaTime * drop);
    14.             }
    15.  
    16.         if (Physics.Raycast(transform.position, transform.forward, out hit, Distance, ~(1<<9) ))
    17.         {
    18.             if(Bounce == true)
    19.             {
    20.                 Vector3 v3NewDirection = Vector3.Reflect ((hit.point - transform.position).normalized , hit.normal);
    21.                 Quaternion newrote = Quaternion.LookRotation(v3NewDirection, Vector3.up);
    22.                 transform.localRotation = newrote;
    23.                     speed *= drag;
    24.             }
    25.             else
    26.             {
    27.                     if(radius > 0)
    28.                     {
    29.                         Instantiate(explosion, transform.position, transform.rotation);
    30.                     }
    31.                 Destroy (gameObject);
    32.             }
    33.                     //Debug.Log("Hit Something");
    34.         }
    35.        
    36.        
    37.             transform.localPosition += transform.forward * Distance;
    38. }
    39.  
    40.  
     
    Last edited: May 22, 2014
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    First of all, [co de] code tags [/code]!

    Second: It looks like you're using the wrong control variable for the last parameter of Slerp. Just like Anything.Lerp, this is a common newbie misunderstanding.

    When you use Lerp/Slerp, the final parameter is a number between 0 and 1. If it's 0, it returns your first value. If it's 1, it returns the second. Anything in between, it returns a smoothly interpolated value between the two.

    So instead of sending it "Time.deltaTime * 2" - which is basically going to always give you a rotation that is very close to the first parameter, but "jitters" slightly towards the second parameter depending on the framerate - you'll want to keep track of a "float" variable, add Time.deltaTime * 2 to THAT variable, and send Slerp that variable instead.
     
  4. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    958
    It doesn't really help that what the poster does here is in fact straight out of the Unity documentation, even though it is actually pretty much a trick usage of lerp, albeit quite common.

    This code, and all other lerps of this style, asymptotically tend towards a value, resulting into a smooth move, slowing down while approaching the target. I simplified the code to just the slerp bit and does seem to manage to do that quite well.

    It boils down to:

    Code (csharp):
    1.  
    2.             Vector3 direction = Target.transform.position - transform.position;
    3.             Quaternion target = Quaternion.LookRotation(direction);
    4.             transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * RotationSpeed);
    5.  
    It will not "slightly jitter to the second parameter depending on the framerate", because the first parameter is the current position, which is altered on every frame.

    So, even though there are better ways to achieve this (see: problems if the framerate drops too much and the actual asymptotic behaviour itself), I do not think it's the slerp that causes the poster's issues.
     
    Last edited: May 21, 2014
  5. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    I think how I instantiate the object is likely important as well... maybe its locking up for some reason??

    Code (csharp):
    1.            
    2.  
    3. for(int shotsfired = 0; shotsfired < bulletspershot+1; shotsfired++)
    4.             {
    5.                 xrotation = (Random.Range(-50+accuracy,50 - accuracy));
    6.                 yrotation = (Random.Range(-50+accuracy,50 - accuracy));
    7.                 mygun.transform.localEulerAngles = new Vector3(mycamera.transform.localRotation.x + xrotation,mycamera.transform.localRotation.y + yrotation,mycamera.transform.localRotation.z);
    8.                 //mygun.transform.localRotation = new Quaternion(mycamera.transform.localRotation.x + xrotation,mycamera.transform.localRotation.y + yrotation,mycamera.transform.localRotation.z, mycamera.localRotation.w);
    9.                 Instantiate(bullet,mygun.position,mygun.rotation);
    10.  
    11.  
     
  6. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    assuming this is the issue, is there a way I can instantiate the object in a non gimbal locked state facing the direction I need it to travel?
     
  7. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    So it seems to want to avoid 0,0,0 world space for some reason.... is there some way to keep it from doing this?
     
  8. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    I really need this. I can't proceed without it...
     
  9. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,500
    pointing towards the floor
    or
    pointing towards the movement parabolic curve shape that ends pointing towards the floor?
    In this case you just need a look at target "last past position" and then flip *-1 the rotation to point where you are going. ;)

    Can you make a drawing of what you need?:confused:
     
  10. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    did so links at the top
     
  11. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    All of my projectiles travel along their local positive Z axis. I tried to slerp the rotation to look towards global down, but at some angles it causes strange results. (the bullets turning away instead of simply looking down) I need the bullets to look down untill they reach a certain point. (close but not exactly global down) then stop rotating towards the ground. if they are no longer in that threshold they then need to begin rotating towards the floor again.

    (as for why, it is because I have a game that uses thousands of bullets at a time and faking the physics without rigid bodies in this way allows me to have that many in the game at one time. This worked fine until I attempted to add in bullet drop by use of rotation. This does not seem like it should be that hard, but it is turning out to be a pain in the butt)
     
  12. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,500
    Sorry i do not understand the drawing and I do not like projectile bullets.

    Is just a parabolic rotation?
    Look image:
    $para.gif

    like this drawing?

    Solution step by step.

    First make an arrow that point a target.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class PointToTarget : MonoBehaviour
    6. {
    7.  
    8.     public GameObject dragTarget; // Drag here your Game Object target
    9.         private Vector3 myVector;
    10.  
    11.  
    12.     void Start () {
    13.  
    14.         if (dragTarget == null)
    15.             Debug.LogError ("ATTENCION: This script ·PointToTarget· needs a GameObject targrt" + "\n");
    16.     }
    17.    
    18.  
    19.    
    20.     void Update () {
    21.         transform.LookAt(dragTarget.transform);
    22.     }
    23. }
    24.  
    You need a game Object as target.


    if the arrow is not pointing correctly (modeling problems), you can add a correction.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class PointToTarget : MonoBehaviour {
    6.  
    7.     public GameObject dragTarget; // Drag here your Game Object target
    8.  
    9.         // Trim Rotation helper just in case
    10.     public float arrowAngleX, arrowAngleY, arrowAngleZ;
    11.    
    12.         private Vector3 myVector;
    13.  
    14.     // Use this for initialization
    15.     void Start () {
    16.                 // Just in case the arrow needs help rotation at start
    17.         arrowAngleX = 90f;
    18.                 arrowAngleY = 0f;
    19.                 arrowAngleZ = 0f;
    20.  
    21.         if (dragTarget == null)
    22.             Debug.LogError ("ATTENCION: This script ·PointToTarget· needs a GameObject targrt" + "\n");
    23.     }
    24.    
    25.     // Update is called once per frame
    26.     void Update () {
    27.         transform.LookAt(dragTarget.transform);
    28.         transform.Rotate (arrowAngleX, arrowAngleY, arrowAngleZ);
    29.     }
    30. }
    31.  



    Now Imagine an arrow in space that points to the past
    You can yous this to make the rotation.

    What you need is your past position (target) and your actual position.
    So the arrow will point to the past.
    If you flip it (-1), it will point to an approximation future.


    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MovDirection : MonoBehaviour {
    6.  
    7.     private Vector3 lastPosition;
    8.     private Vector3 actualPosition;
    9.    
    10.  
    11.  
    12.     void Start () {
    13.         lastPosition = transform.position;
    14.     }
    15.  
    16.  
    17.  
    18.     void FixedUpdate() {
    19.         lastPosition = actualPosition;  // Here you get the target (the past position)
    20.         actualPosition = transform.position;
    21.  
    22.         transform.LookAt(lastPosition);
    23.         transform.Rotate (90f, 0f, 0f);
    24.     }
    25. }
    26.  
    I did not test it and I'm new coding.
     
    Last edited: May 22, 2014
  13. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,500
    At line 22
    Code (csharp):
    1.  
    2. transform.Rotate (90f, 0f, 0f);
    3.  
    you can add 180° for example and your GameObject Arrow will point to the future approximation and not to the past.

    Ps: If is what you need. If is not what you need, I can´t help you. I has to go! bb
     
  14. The_Raz

    The_Raz

    Joined:
    Feb 8, 2014
    Posts:
    79
    I can't seem to get it to work correctly, I also don't think this would stop the rotation at true down.