Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • 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.

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

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

How to use Quaternion.Slerp with transform.LookAt? 3 Answers

unwanted rotation in y axis 0 Answers

[Solved] Quaternion from IMU sensor to GameObject Orientation problem 3 Answers

How to use Quaternion.slerp and Quaternion.LookRotation with a child gameobject 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges