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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Slider that adjusts time

Discussion in 'Scripting' started by PingSharp, Apr 17, 2020.

  1. PingSharp

    PingSharp

    Joined:
    Apr 17, 2020
    Posts:
    13
    Hello. I'm creating a game where i need a slider to be able to adjust time, so that the max value speeds up time by say 10x, and the lowest either freezes time or (i don't know if that's possible: reverse it). The problem here is that I couldn't find any information on how to do it, so I tried putting two different examples together (one explaining a slider script, and one explaining how to adjust time). I didn't get anywhere trying this, so it would be nice if anyone just explained how to do things, or just get started.

    I have two scripts, one for a slider that adjusts time and one for time in general. Should I delete the one for time and just go with the slider that adjusts the time? I also need some help with the scripting (C#).

    Thank you.

    Edit: I'm also pretty lost in this forum's different flairs so please don't mind me posting this if it totally doesn't fit in scripting
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    Sliders by default only return 0 to 1. For your slider, change it to return 0 to 10. It's the fields named Min Value and MaxValue on the slider UI component.

    If you do any Slider use tutorial there will be a OnValueChanged delegate changed that perhaps changes volume or does something else with the passed float value, such as displays it onscreen.

    In your case, modify that delegate (function) so that it just assigns that incoming value to
    Time.scaleTime
    instead and your time factor will change.

    CAUTION: some Slider tutorials are actually completely useless for this, such as the very first one that comes up in Google: This first search result actually uses a Slider to display a code value, and specifically deletes the interactivity of it. I don't know how this one got so high in the rankings but: DO NOT USE THIS TUTORIAL: https://www.mvcode.com/lessons/using-sliders-in-unity-aaron

    The above tutorial does NOT give you a Slider that you can control; For some bizarre reason he uses a slider when a Filled Image would have done exactly the same thing, and he even goes so far as to DELETE the interactivity handle, and repurpose the Image inside the pre-made Slider to make it Filled. :facepalm:

    Find a slider tutorial that controls a volume setting, for instance, or just displays the OnValueChanged number to Debug.Log(). Something like that will suffice as a starting point for a responder script.
     
  3. davidnibi

    davidnibi

    Joined:
    Dec 19, 2012
    Posts:
    424
    I think I actually tried that 'article' years ago and came to the same conclusion!
     
  4. PingSharp

    PingSharp

    Joined:
    Apr 17, 2020
    Posts:
    13
    So this is my entire script, sorry if I misunderstood you somehow but something doesn't seem to be working.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Time : MonoBehaviour
    6. {
    7.  
    8.     public float time = 10f;
    9.  
    10.     void Update()
    11.     {
    12.         Time.scaleTime(0, time * Time.deltaTime);
    13.     }
    14.  
    15.     public void AdjustTime(float newTime)
    16.     {
    17.         time = newTime;
    18.     }
    19.  
    20. }
    I did change the min/max value in the slider though.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    Very close !!!

    So your time variable, start that off most likely at 1.0 instead of 10f, otherwise you will start out in crack smokin' turbo mode.

    Line 12 above, you want to just assign to Time.timeScale, like this:

    Code (csharp):
    1. Time.timeScale = time;
    That's literally it. Time.timeScale is a multiplier on the whole Time system, so you don't need to do the Time.deltaTime multiplication.

    ALTERNATE SUGGESTION:

    As a further optimization, you COULD do away with the time variable entirely, remove the Update() function and put this line inside your AdjustTime function:

    Code (csharp):
    1. Time.timeScale = newTime;
    Only do one of the two things above, not both!!
     
  6. Aref1996

    Aref1996

    Joined:
    Apr 26, 2019
    Posts:
    2
    Use This Code...
    Code (CSharp):
    1.     using System.Collections;
    2.     using System.Collections.Generic;
    3.     using UnityEngine;
    4.     using UnityEngine.UI;
    5.    
    6.     public class Time : MonoBehaviour
    7.     {
    8.     public Slider timeSlider;
    9.        
    10.     private void LateUpdate()
    11.     {
    12.          Time.timeScale = timeSlider.value;
    13.     }
    14.     }
    15.  
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    Oooh... I just noticed... you better not name that Monobehavior Time.cs... try maybe a different class name like TimeChanger or TimeSlider... if you use Time you will not be able to access UnityEngine.Time without some extra qualifications.

    Best not to reuse names from Unity, such as
    Time
    ,
    Debug
    ,
    Input
    , etc. Technically you CAN reuse the names by fully qualifying the namespace, but that would earn you scowly face where I work.
     
  8. PingSharp

    PingSharp

    Joined:
    Apr 17, 2020
    Posts:
    13
    "error: Assets\Scripts\TimeSlider.cs(12,14): error CS0117: 'Time' does not contain a definition for 'timeScale'"
     
  9. PingSharp

    PingSharp

    Joined:
    Apr 17, 2020
    Posts:
    13
    Okay, so now my script looks like this:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TimeSlider : MonoBehaviour
    6. {
    7.  
    8.     public float time = 10f;
    9.  
    10.     void Update()
    11.     {
    12.         Time.timeScale = time;
    13.     }
    14.  
    15.     public void AdjustTime(float newTime)
    16.     {
    17.         time = newTime;
    18.     }
    19.  
    20. }
    and I am getting this error message:
    InvalidOperationException: EnsureRunningOnMainThread can only be called from the main thread
    UnityEngine.Object.EnsureRunningOnMainThread () (at <0d01204b437e47c1a78b600b597a89f4>:0)
    UnityEngine.Object.GetInstanceID () (at <0d01204b437e47c1a78b600b597a89f4>:0)
    UnityEngine.Object.IsNativeObjectAlive (UnityEngine.Object o) (at <0d01204b437e47c1a78b600b597a89f4>:0)
    UnityEngine.Object.CompareBaseObjects (UnityEngine.Object lhs, UnityEngine.Object rhs) (at <0d01204b437e47c1a78b600b597a89f4>:0)
    UnityEngine.Object.op_Inequality (UnityEngine.Object x, UnityEngine.Object y) (at <0d01204b437e47c1a78b600b597a89f4>:0)
    UnityEngine.Events.PersistentCall.ValidateTargetAssemblyType () (at <0d01204b437e47c1a78b600b597a89f4>:0)
    UnityEngine.Events.PersistentCall.OnAfterDeserialize () (at <0d01204b437e47c1a78b600b597a89f4>:0)

    What does that mean, and how do I solve it? Someone said restart Unity, but that clearly doesn't work
     
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    Read my post above. You named your script Time. This hides the UnityEngine Time class you're trying to access.

    Read my suggestion to fix it above.
     
  11. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    When you rename a monobehavior class you have to rename the file as well, so no more Time.cs, call the file TimeSlider.cs or whatever classname you used. Match capitalization please!