Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 /
avatar image
0
Question by castor · Sep 30, 2013 at 08:52 PM · timedeltatimedialogskip

How to fast forward time (or just skip it) properly?

Not sure what is exactly going wrong here.

I have a world time that runs on update:

     if (!worldInteractions.worldIsPaused && !worldInteractions.showMainMenu){
         worldTime += Time.deltaTime;
     }

and I use that time to drive the game world clock :

 function GameTime () {
     if (worldTime - lastChange > 10) {    //Decides how many seconds a game 'minute' lasts.    
         minutes++;
         
         if (minutes == 60) {            
             minutes = 0;
             hour++;
             if (hour == 12) {
                 if (ampm == "am") {
                     ampm = "pm";
     
                 }
             }
             if (hour == 13) {
                 hour = 1;
             }
         }
         lastChange = worldTime;
     }
 }


In my project, when the player is in a dialog, he is able to skip a dialog line and also advance the time it would take to display it(e.g. if a line of text would display for 5 seconds and the player skips it, then it will be 5 seconds later).

This is how a dialog is currently displayed (I'm doing a typewriter effect from a script shown in Unity wiki I think):

 function DoTextLine (){
     currentDisplayLine = null;

     for (var letter in currentScriptStep.textLine.ToCharArray()) {
         currentDisplayLine += letter;
         yield WaitForSeconds (letterPause);
     }
     
     yield WaitForSeconds (endDialogPause);
     
     currentState = DialogStates.Idle;
 }

And when the player presses a key to fast forward that dialog I do this:

 function SkipDialogLineAction (){
     if (dialogInteractions.currentState == DialogStates.ShowTextLine){
         Time.timeScale = 90;
     }
 }    

and once the textLine has been fully displayed in faster speed I go back to the normal timeScale:

 if(currentState == DialogStates.Idle && Time.timeScale == 90){
     Time.timeScale = 1;
 }

I thought this was working all correctly but I noticed that time passes much faster than it should. If I skip a dialog line of 5 secs I end up passing almost 30 secs from the worldTime variable. I'm wondering what I could be doing wrong. I'm not totally comfortable with Time.time and Time.deltaTime and wondering if there is a error there? Or if maybe using yield on the Typewriter effect could be causing the issues with the timeScale difference...

Or maybe there is a much better way to achieve this?

Any help very appreciated!

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
2
Best Answer

Answer by robertbu · Sep 30, 2013 at 09:39 PM

When you set 'Time.timeScale = 90', time will pass 90 times as fast. This means that Time.deltaTime will also be accelerated by 90x. So if it takes 1/3 of a second to skip the dialog, your worldTime will advance by 30 seconds. I see two possible fixes. First, you could change your letterPause variable to something small to cause the typing to go quickly rather than increasing Time.timeScale. Or you can save and restore worldTime. For the latter I mean something like:

 function SkipDialogLineAction (){
     if (dialogInteractions.currentState == DialogStates.ShowTextLine){
        Time.timeScale = 90;
        worldTimeSaved = worldTime;
     }
 }    
 
 if(currentState == DialogStates.Idle && Time.timeScale == 90){
     Time.timeScale = 1;
     worldTime = worldTimeSaved + 5.0;
 
 }
Comment
Add comment · Show 8 · 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 castor · Oct 01, 2013 at 02:08 AM 0
Share

Thanks for the suggestions. I still don't quite understand why its bad that the deltaTime goes faster.

So if it takes 1/3 of a second to skip the dialog, your worldTime will advance by 30 seconds.

Just for me to understand, lets say the dialog line would normally take 10 seconds. When I do the fast forward time will go faster 90x so ins$$anonymous$$d of 10 sec it would be 0.1sec right? What I don't understand is why the worldTime doesn't also just go faster so that in 0.1 secs it adds 10 seconds to its total time (just like it would have it I had waited for the dialog line to go).

As for the suggestions, I have other things attached to the worldTime (sun angle and rotation and other events dependent on what time it is on the clock) so if I only speed up the letterPause I won't really get the speed up that I need for the other things in the world.

The save/restore worldTime seems like a good suggestion but still makes me wonder why its "wrong" in the first place. I think I need to understand why there is a discrepancy between both!

avatar image robertbu · Oct 01, 2013 at 03:20 AM 1
Share

Your logic is backwards. Here is a script to show you what is going on. Attach it to an empty game object, set factor as appropriate, and hit play:

 #pragma strict
 
 var factor = 90.0;
 private var sumTime = 0.0;
 
 function Start() {
     Time.timeScale = factor;
 }
 
 function Update() {
     sumTime += Time.deltaTime;
 }
 
 function OnGUI() {
     GUI.Label(Rect(0,0,500, 50), "Time since startup: "+Time.realtimeSinceStartup);
     GUI.Label(Rect(0,75,500, 50), "Time.time: "+Time.time);
     GUI.Label(Rect(0,150,500, 50), "Sum of deltaTime "+sumTime);
 }

The first number is real world time. That is, it would match a stop watch or the second hand on your watch. The second number is Time.time which is the game time. The third number is the sum of all deltaTimes which will be very close to Time.time.

With the default value of 90 for 'factor', you will see that when one second passes in the real world, you end up with 90 seconds passing in the game world. At 10 seconds real time, you have 900 seconds of game time.

Think about what happens in a game. If we are scaling things by deltaTime for movement, and we speed up Time.timeScale by a factor of 90, then each deltaTime will also be increased by a factor of 90 causing things to move further each frame.

avatar image castor · Oct 01, 2013 at 03:46 PM 0
Share

Thanks for taking the time to explain me this!

I think I now understand the concept that time.deltaTime will increase exponentially depending on how much I multiply it by the timeScale.

This makes sense to me :

With the default value of 90 for 'factor', you will see that when one second passes in the real world, you end up with 90 seconds passing in the game world. At 10 seconds real time, you have 900 seconds of game time.

Now I made a little experiment on my side. I scripted a character walking to another character and say a line. Once the line is said I paused the editor window programmatically to see the times I get.

This are the additions I did to the gui times (the game clock starts at 7.32pm):

 function OnGUI() {
     GUI.Label(Rect(0,0,500, 50), "Time since startup: "+Time.realtimeSinceStartup.ToString("f2") + "secs");
     GUI.Label(Rect(0,20,500, 50), "Time.time: "+Time.time.ToString("f2") + "secs");
     GUI.Label(Rect(0,40,500, 50), "Sum of deltaTime "+sumTime.ToString("f2") + "secs");
     GUI.Label(Rect(0,60,500, 50), " gameTime " + worldTime.ToString("f2") + "secs");
     GUI.Label(Rect(0,80,500, 50), " gameClock " + hour + ":" + $$anonymous$$utes);
 }


Case 1: TimeScale is always 1 through the whole thing. This is what i get when the game is paused at the end of the dialog line:

alt text

Case 2: Here I speed up the timeScale to 90 the moment the character starts to say the line. This are the results at the end of the dialog line:

alt text

And this is the exact moment the character starts to say the line and I change the timeScale from 1 to 90 (2.13secs into the game):

alt text

Now what I would assume is that the second example would have Time.time/Sum of deltaTime/gameTime just like the first case BUT with a shorter Time since startup since I made the dialog that originally took 3 seconds to take only 0.7 secs.

Thanks for the patience so far :)

avatar image castor · Oct 01, 2013 at 04:23 PM 0
Share

What I keep thinking is if I'm staying at timeScale = 90 for too long. $$anonymous$$aybe what is happening is that the "speed up" dialog line is actually taking longer than it should?

What happens to this function that I use for the time it takes to say a line? Does it get scaled correctly?

 function DoTextLine (){
     currentDisplayLine = null;
  
     for (var letter in currentScriptStep.textLine.ToCharArray()) {
        currentDisplayLine += letter;
        yield WaitForSeconds (letterPause);
     }
  
     yield WaitForSeconds (endDialogPause);
  
     currentState = DialogStates.Idle;
 }

If the dialog line takes 3.13 secs (5.26 - 2.13 secs) at timeScale =1, then if it would take 0.03 secs at timeScale = 90 right?

So on the Case 2 the Time since startup should read 2.13/2.14 secs and not 2.92secs, its like the function DoTextLine is taking a lot longer than 0.03 seconds to execute.

avatar image robertbu · Oct 01, 2013 at 05:55 PM 0
Share

Case 2: Here I speed up the timeScale to 90 the moment the character starts to say the line. This are the results at the end of the dialog line:

Now what I would assume is that the second example would have Time.time/Sum of deltaTime/gameTime just like the first case BUT with a shorter Time since startup since I made the dialog that originally took 3 seconds to take only 0.7 secs.

The difference between Time.time and Time startup is approximately what I would expect. If your dialog is taking .25 seconds and you set Time.timeScale = 90, then Time.time will increase by approximately 22.5 during the time the dialog is up. I don't know how you are capturing your data, but 21 seconds different is approximately what I would expect to see.

But as mentioned earlier, saving and restoring worldTime is a solution regardless of how these numbers pan out.

Show more comments
avatar image
0

Answer by castor · Oct 01, 2013 at 08:58 PM

In case it helps future people (and feel free to correct it Robertbu!) here is the solution I'm using based on the discussion we had, seems to be working only being about 1 to 2 seconds off.

 function SkipDialogLineAction (){
     if (dialogInteractions.currentState == DialogStates.ShowTextLine){
         //Store the current world time and the dialogTimeLeft
         var currentWorldTime = scriptWorld.worldTime;
         var dialogTimeLeft = dialogInteractions.textLineDisplayTimeLeft + dialogInteractions.endDialogPause;
         
         //Cancel current dialog
         dialogInteractions.StopCoroutine("DoTextLine");
         dialogInteractions.currentDisplayLine = null;
         dialogInteractions.currentState = DialogStates.Idle;
 
         //Advance game time based on how much of the dialog was left
         Time.timeScale = 90;
         yield WaitForSeconds (dialogTimeLeft);
         
         //Bring timescale back to 1 and correct worldTime
         Time.timeScale = 1;
         scriptWorld.worldTime = currentWorldTime + dialogTimeLeft;
     }
 }
Comment
Add comment · 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

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

14 People are following this question.

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

Related Questions

Force mode and delta timing 1 Answer

When to use Time.deltaTime? 3 Answers

Different behavior between editor and standalone changing time step 0 Answers

High Speed 1 Answer

Time.timeScale and Time.fixedDeltaTime 1 Answer


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