Search Unity

How do I make an object's rotation only happen for a specific duration of time?

Discussion in 'Scripting' started by yah00answers, May 8, 2022.

  1. yah00answers

    yah00answers

    Joined:
    Feb 7, 2022
    Posts:
    4
    I hope my explanation makes sense but I'm making an experimental 3D game for an intro to game dev class. The objective is to collect spheres of light in a dark forest (OnTriggerEnter of player walking up to the sphere and touching colliders), and with each trigger, the directional light should slightly rotate for, let's say 5 seconds. once all of the light is collected, it becomes daytime. This is what I have so far:


    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class LightScript : MonoBehaviour
    {
    void Update()
    {
    this.transform.RotateAround(Vector3.zero, Vector3.right, 0.1f * Time.deltaTime + 5);
    if(Time.deltaTime = Time.deltaTime + 5)
    {
    this.transform.RotateAround(Vector3.zero, Vector3.zero, 0);
    }
    }
    }


    Not sure how to proceed, please help! It's rotating the way I want it to, I can change the speed, but I want it to stop after 5 seconds. It's due Monday and I keep getting stuck trying to solve things.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    You want to accumulate the game state in a simple variable, such as either an integer or a float.

    It might count (for example) up from 0 to 10 and then the condition has been met.

    Based on that variable, you would use that to drive a rotation of whatever you want to rotate.
     
  3. yah00answers

    yah00answers

    Joined:
    Feb 7, 2022
    Posts:
    4
    Could you possibly give me an example of how that would look in code? I'm so lost when it comes to following C# syntax.
     
  4. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    Oof. I highly recommend you find a c# primer website and work through the tutorials before continuing with your course. Anything you're likely to encounter in an intro to game development class will be covered.
     
  5. yah00answers

    yah00answers

    Joined:
    Feb 7, 2022
    Posts:
    4
    It's the end of the semester, honestly my prof wasn't too helpful and a lot of what the students learned was more of self-research than curriculum-based. So now I'm scrambling to finish the final project but it's hard for me to troubleshoot on the internet because I can't find answers particular to my situation.
     
  6. yah00answers

    yah00answers

    Joined:
    Feb 7, 2022
    Posts:
    4
    Also, do you mind explaining where the 5 second variable would fit in the // this.transform.RotateAround(Vector3.zero, Vector3.right, 0.1f * Time.deltaTime + 5); // ? I'm struggling to understand how to make this command durational.
     
  7. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    Yeah, this type of class is usually complete garbage, thrown together to attract the yoof but of absolutely no marketable value.

    You've identified Time as a useful class, but you've not understood the purpose of the various values within it:

    Time.deltaTime : This is the amount of time since Update was last called, and is framerate-dependent.
    Time.time : This is the amount of game time since you hit play or launched the app. It is affected by altering Time.timeScale
    Time.timeScale : Alter the relationship between real time and game time. Setting it to zero is usually an important part of pausing the game.

    Let's start by stating the problem precisely:

    When the player collides with the object, you want it to spin for five seconds. You only want this to happen once.

    One way to achieve the timed rotation is with a coroutine. Coroutines are ideal for processes that start and then continue for a period of time; they avoid the need to use 'state' variables to remember where you were up to the next time Update is called.

    Here's an example of a coroutine that does what you want:

    Code (CSharp):
    1.     IEnumerator RotateForFiveSeconds()
    2.     {
    3.         float endTime = Time.time + 5f;
    4.         while (Time.time < endTime)
    5.         {
    6.             transform.RotateAround(Vector3.zero, Vector3.right, Time.deltaTime);
    7.             yield return new WaitForEndOfFrame();
    8.         }
    9.     }
    The important line to note in there is the 'yield'. This is telling Unity to go away and come back when the end of the frame is reached. This is what makes coroutines dfifferent from normal methods: they don't have to finish and return immediately.

    Now we just need to trigger the coroutine, and do it just once. One way to do this is to disable the collider - this may or may not suit your needs:

    Code (CSharp):
    1.         public void OnCollisionEnter(Collision collision)
    2.         {
    3.             //Assuming the only possible collision is with the player
    4.             StartCoroutine(RotateForFiveSeconds());
    5.             //Turn off our collider so the collision cannot retrigger
    6.             GetComponent<Collider>().enabled = false;
    7.         }
    8.  
     
    Last edited: May 8, 2022