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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Recoil Slerping back to original rotation

Discussion in 'Scripting' started by xNIkurasu, Aug 23, 2018.

  1. xNIkurasu

    xNIkurasu

    Joined:
    May 18, 2018
    Posts:
    7
    Hello. I am making a small FPS game so I can get used to gun mechanics etc. and I am making a recoil script at the moment, where after I shoot, the gun rotates either to the left or to the right (because a random number generator). However, I want my gun to rotate back to its original rotation after a certain amount of time after i stopped shooting. With my current script, it just puts my gun in a weird rotation.

    Code (CSharp):
    1. public Quaternion hipFire;
    2.     public GameObject ar;
    3.     int x;
    4.     float f;
    5.    
    6.     void LateUpdate () {
    7.         StartCoroutine(Recoil());
    8.        
    9.     }
    10.     IEnumerator Recoil()
    11.     {
    12.         if (Input.GetMouseButtonDown(0))
    13.         {
    14.             f = f + 0.3f;
    15.             x = Random.Range(0, 2);
    16.             if (x == 0)
    17.             {
    18.                 transform.Rotate(0, 3.5f, 0);
    19.                 f = f + 0.25f;
    20.             }
    21.  
    22.             if (x != 0)
    23.             {
    24.                 transform.Rotate(0, -3.5f, 0);
    25.                 f = f + 0.25f;
    26.             }
    27.             yield return new WaitForSeconds(.2f + f);
    28.             ar.transform.rotation = Quaternion.Slerp(ar.transform.rotation, hipFire, 15 * Time.deltaTime);
    29.  
    30.             f = -0.3f;
    31.         }
    32.     }
    33. }
    I know this code is very messy and could be improved, but this is just the basic stuff that i want to accomplish. Ar.transform.rotation = Quaternion.Slerp(ar.transform.rotation, hipFire, 15 * Time.deltaTime); is the line that should bring the gun back to its original rotation. ar is the gun object in my scene. And also, f is supposed to be the reset timer for the recoil. If you want to provide code to help me then i would really appreciate it, but i dont expect that in any way - just telling me what to do is just as helpful! Thanks for reading.
     
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,558
    I suggest that you apply first hip fire, without any other rotation changes, or even directly to rotation, to see, if Quaterion is parametrs are correct. If hip fire don't set ar rotation directly, then you found your initial problem.

    also, f = f + x ; is the same as f += x ; So use the second, as is shorter and quicker.
    Try use meaningful variables names. hipFire don't appears anything like rotation even it is Quaternion. It should clearly indicate, what it is. At least put comments. You will appreciate yourself in future.
     
  3. xNIkurasu

    xNIkurasu

    Joined:
    May 18, 2018
    Posts:
    7
    okay, first of all: thanks for replying! Now, doing what you told me to do definitely helped. I noticed that the hipFire was in fact the problem. Now that I have got the right coordinates, I tried going back to Slerp. However, now it doesn't slerp back to the original rotation. It only goes back a little bit and not fully and it's not smooth at all, got any tips for that? But still, thanks so much for the reply.
     
  4. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,558
    No probs.
    Check if you not overriding your reference quaternion, for which you target return rotation. You can always use quaternion.eulerAngles, to get idea, what it looks like in degrees.
    It makes sense o use it, if you have one axis changed, but if multiple axis is changed, you may get confused, if you are not familiar, so is not always good method.
     
  5. xNIkurasu

    xNIkurasu

    Joined:
    May 18, 2018
    Posts:
    7
    Okay, so now I tried switching " Quaternion.Slerp(transform.rotation, hipFire, 15 * Time.deltaTime);" to " Quaternion.Slerp(hipFire, transform.rotation, 15 * Time.deltaTime);" and now after the reset time has ended, the gun goes back to its original rotation, but it does that instantly. Is there a way to fix that?
     
  6. xNIkurasu

    xNIkurasu

    Joined:
    May 18, 2018
    Posts:
    7
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,558
    Quaternion.Slerp takes two rotation arguments, of which first one is the current state, and second is the target state. You need get to understand this, to get correct result. Otherwise you get funny behaviors. So initial way was correct.
    If your rotation don't comes back with Lerp / Slerp, then means, you still got problem somewhere with logic and hipFire.
    Use debug/breakpoints to find out, what writes where to it. Oh btw, mind data is passed by reference, not a copy.
     
  8. xNIkurasu

    xNIkurasu

    Joined:
    May 18, 2018
    Posts:
    7
    Okay so, I think I figured out what the problem is. Perhaps the slerp only doesnt work properly is because of MouseButtonDown. Because after I used MouseButton instead of MouseButtonDown, it did slerp like it should, but now its just repeating the coroutine a lot of times, is there a way to fix that?
     
  9. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,558
    That appears you have continuously triggering coruotine.

    I would rather than having input detection in the if statement, put bool flag, that which triggers condition.

    What you need, is trigger to initiate lerp procedure. Mouse input should be somewhere triggering bool flag.
    When this flag is enabled, it allows lerp to do the job. At the same time, you have another procedure, which after given duration from the bool flag being triggered true, disables this flag. Means your rotation has returned.
    This way, you decouple your script from direct input. And you can trigger this flag with anything else you like, if ever needed in future.
     
  10. xNIkurasu

    xNIkurasu

    Joined:
    May 18, 2018
    Posts:
    7
    Im not sure if I understood what you said (i dont know what boolean flags are haha), but I tried this:
    Code (CSharp):
    1. void LateUpdate () {
    2.         StartCoroutine(Recoil());
    3.         while (!isShooting && transform.localRotation != hipFire)
    4.         {
    5.             transform.localRotation = Quaternion.Slerp(transform.localRotation, hipFire, 0.5f);
    6.         }
    7.  
    8.     }
    9.     IEnumerator Recoil()
    10.     {
    11.         if (Input.GetMouseButtonDown(0))
    12.         {
    13.             isShooting = true;
    14.             f += 0.3f;
    15.             x = Random.Range(0, 2);
    16.             if (x == 0)
    17.             {
    18.                 transform.Rotate(0, 3.5f, 0);
    19.                 f += 0.25f;
    20.                
    21.             }
    22.  
    23.             if (x != 0)
    24.             {
    25.                 transform.Rotate(0, -3.5f, 0);
    26.                 f += 0.25f;
    27.              
    28.             }
    29.            
    30.             yield return new WaitForSeconds(1f + f);
    31.             isShooting = false;
    32.            
    33.             f = -0.3f;
    34.         }
    35.     }
    So after shooting, isShooting is true; and after a certain amount of time, isShooting is set to false. After it becomes false, the if statement in lateupdate is called where it should slerp as long as localrotation and hipfire arent the same and isShooting is false, but that didnt work either. What am I doing wrong, or did i misunderstand your tip?
     
  11. xNIkurasu

    xNIkurasu

    Joined:
    May 18, 2018
    Posts:
    7
    UPDATE: i changed the while statement to an if statement and now its finally working! Thank you so so much for your help!
     
  12. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,558
    Cool.

    Just to explain, since you had this right anyway:
    Flag is another term, for boolean state false, or true.
    It just indicates, I am on, or I am off. Just like conquering land and sticking flag; "This is our now" ;)
     
    xNIkurasu likes this.