• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
1
Question by KevinKLV · Feb 01, 2017 at 09:15 AM · rotationtransformquaternionslerpdeltatime

[Solved] Smooth rotation with keydown

  • Details:

I have a sphere that is constantly rotating in the 'y' axis, and I want to stop rotation, and go back to initial position in a smooth transition after I press 'Space'.

  • Problem:

When I press space the rotation stops, but there is no transition to the original position.

  • Code

    public class Rotation : MonoBehaviour { public float X; public float Y; public float Z;

       private Quaternion OriginalRotation;
         private Quaternion CurrentRotation;
     
         // Use this for initialization
         void Start()
         {
             OriginalRotation = gameObject.transform.rotation;
             
         }
     
         // Update is called once per frame
         void Update()
         {
             rotate();
         }
     
         void rotate()
         {
             float smooth = 0.01f;
     
             if (Input.GetKeyDown(KeyCode.Space))
             {
                 print("Space bar pressed");
     
                 Y = 0;
                 transform.rotation = Quaternion.Slerp(CurrentRotation, OriginalRotation, Time.deltaTime * smooth);
                 //transform.rotation = OriginalRotation;
             }
             else
             {
                 gameObject.transform.Rotate(X, Y, Z * Time.deltaTime);
                 CurrentRotation = gameObject.transform.rotation;
             }          
         }
     }
    
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Kossuranta · Feb 01, 2017 at 10:55 AM

I can see two mistakes which are the reason why your code doesn't work. First you are using Input.GetKeyDown which will only be true during single frame, you need to use Input.GetKey instead. Then second thing is that you have Time.deltaTime in your lerp where both positions are always at the same places meaning it will only move "once" as Time.deltaTime is time between two frames. Here is really good explanation of this.


Here is code that should work. While spacebar is pressed down the object will rotate from currentRotation to originalRotation. I also changed your code a bit as generally variables should be written with small first letter and functions with capital first letter. You also created new variable smooth in your Rotate-function for no reason, so I moved it too. And you can directly call transform, no need to write gameObject.transform.

 public class Rotation : MonoBehaviour
 {
     public float X, Y, Z;
     private Quaternion originalRotation;
     private Quaternion currentRotation;
     private float smooth = 0.01f;
     private float lerpTimer = 0;
 
     // Use this for initialization
     void Start()
     {
         originalRotation = transform.rotation;
     }
 
     // Update is called once per frame
     void Update()
     {
         Rotate();
     }
 
     void Rotate()
     {
         if (Input.GetKey(KeyCode.Space))
         {
             print("Space bar pressed");
 
             Y = 0;
             lerpTimer += Time.deltaTime;
             transform.rotation = Quaternion.Slerp(currentRotation, originalRotation, lerpTimer);
         }
         else
         {
             transform.Rotate(X, Y, Z * Time.deltaTime);
             currentRotation = transform.rotation;
             lerpTimer = 0;
         }
     }
 }

If you want your reset rotation to work so you can only tap space and it will rotate back to original position and then continue rotating, you will need to use Coroutine.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KevinKLV · Feb 01, 2017 at 09:01 PM 0
Share

Thank you @kossuranta for the help. I am new to C# and Unity, and to coding in general. I really appreciate the tips on C# coding conventions. I'm learning this on my own by building small projects and it is always good to have someone with more experience checking your code.

I will read about Coroutine to see how I can make my rotation to rotate back to its original position.

The smooth variable was from an old code I was trying.

Cheers

avatar image
1

Answer by KevinKLV · Feb 02, 2017 at 12:59 AM

Just in case someone would like to know how I solved my problem.

Objective

  1. Having a sphere rotating constantly at start.

  2. When a key is pressed rotation stops

  3. Sphere rotates back to its original position smoothly

Problem

Sphere was stopping but did not come back to original position. Either I needed to hold the key pressed (GetKey) or I needed to pressed several timer (GetKeyDown)

Solution

I thought that because only the rotation back would work when the input was received, what if I stop rotation only, and then check if rotation had stopped. If so, why not running another function to get the sphere back to its original position.

Code


 public class Rotation : MonoBehaviour
 {
     //Variable for parameter avaliables in the Inspector
     public float rotationSpeed;
     public float returnSpeed;
 
     //Variables declared privatly only for scrip mod
     private float X, Y, Z;
     private float lerpTimer = 1;
     private Quaternion originalRotation;
     private Quaternion currentRotation;
     
 
     // Use this for initialization
     void Start()
     {
         //Orignal Rotation value is stored in variable at start
         originalRotation = transform.rotation;
     }
 
     // Update is called once per frame
     void Update()
     {
         //Rotation function is called to continously rotate sphere
         Rotate();
 
         //checks if rotation stops and if so returns sphere to original position
         if (rotationSpeed == 0)
         {
             RotateOrigin();
         }
     }
 
     //rotate function
     void Rotate()
     {
         //when space key is pressed rotation speed sets to zero
         if (Input.GetKey(KeyCode.Space))
         {
             print("Space bar pressed");
             rotationSpeed = 0;
         }
         else
         {
             //keeps sphere rotating continuously
             Y = rotationSpeed;
             transform.Rotate(X, Y, Z * Time.deltaTime);
             currentRotation = transform.rotation;
             lerpTimer = 0;
         }
     }
 
     //Go back to orinal position function
     void RotateOrigin()
     {
         //set lerp for smooth return to original position.
         lerpTimer += Time.deltaTime;
         transform.rotation = Quaternion.Slerp(currentRotation, originalRotation, lerpTimer);
     }
 }



This worked for me. Please feel free to comment and to criticize my solution. I tried to use a Coroutine but I could not make it work. So feel free to post a workable example if you have one.

Cheers

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Kossuranta · Feb 02, 2017 at 07:31 AM 0
Share

Here is version with coroutine. I didn't test it, but I think it should work.

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Rotation : $$anonymous$$onoBehaviour
 {
     public float X, Y, Z;
     private Quaternion originalRotation;
     private Quaternion currentRotation;
     private float smooth = 0.01f;
     private float lerpTimer = 0;
     private WaitForEndOfFrame waitFrame = new WaitForEndOfFrame();
     private bool rotating = true;
 
     // Use this for initialization
     void Start()
     {
         originalRotation = transform.rotation;
     }
 
     // Update is called once per frame
     void Update()
     {
         Rotate();
     }
 
     void Rotate()
     {
         if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space))
         {
             print("Space bar pressed");
             lerpTimer = 0;
             Y = 0;
             rotating = false;
             StartCoroutine(ResetRotation());
         }
         else if(rotating)
         {
             transform.Rotate(X, Y, Z * Time.deltaTime);
             currentRotation = transform.rotation;
         }
     }
 
     IEnumerator ResetRotation()
     {
         while(lerpTimer < 1)
         {
             lerpTimer += Time.deltaTime;
             transform.rotation = Quaternion.Slerp(currentRotation, originalRotation, lerpTimer);
             yield return waitFrame;
         }
         rotating = true;
     }
 }

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to use Quaternion.Slerp with transform.LookAt? 1 Answer

Can't really grasp how to keep my player level on X and Z while using LookRotation 0 Answers

unwanted rotation in y axis 0 Answers

Rotating Vector3, linecast 1 Answer

Help with rotating camera around object based on mouse input 0 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges