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 Rick74 · Jan 21, 2014 at 06:04 PM · javascriptpauseclock

properly handling pause functionality with javascript/unityscript?

So within my game I have a clock script, which keeps track of it's own float based off of Time.time. You can manipulate it's verion of Time.time,you can pause time, count down time whatever you would like.

There is also a boolean ("if paused") attached to this clock script.

Up until this point, I've been handling this wrong and basically on everything that I need to be pausable I have it get the clock script, and in function Update, check the status on every frame if pause has happened.

 pause = Clock.GetComponent(clockScript).paused
 
 if (pause)
 {
   yadda yadda yadda...
 }
 

I was talking to someone last night who's more experienced at code suggest to me to have whatever button or action that pauses the game, to basically do a check of all units currently in game that can be paused and then perform a co routine (function) to pause them, and of course the same to unpause.

So I "think" what he's suggesting is...

 Funtion PauseEverything ()
 {
     Object[] objects = FindObjectsOfType (any object I want paused)
     Run a Pause Function that each object that you can pause would have in it's script.
 }
 

This sounds great but how do I get multiple scripts with multiple names to call out the same function? And the other worry I have is that I heard "FindObjects" or "GameObjects.Find..." is a very slow process and should be used sparingly especially during gameplay. I'm not sure if this all makes sense, I've only been coding for about 5 months now so I'm still learning lots. Of course any help on clearing this up would be appreciated.

Comment
Add comment · Show 1
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 Jeff-Kesselman · Jan 22, 2014 at 01:39 AM 1
Share

Thats Javascript, not Java.

Two VERY different languages.

(And actually its not really Javascript either but UnityScript. Both Javascript and UnityScript derive from EC$$anonymous$$AScript but there are some important differences between the two. However most people in the unity community call it Javascript due to Unity referring to it that way.)

3 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by HappyMoo · Jan 21, 2014 at 10:19 PM

You don't need to implement your own Time that you can stop.

That's what timeScale is for. And you don't need to tell every Object that the game paused, because they will move based on deltaTime, which means they won't move anymore and on timeScale=0 FixedUpdate isn't called anymore.

Comment
Add comment · Show 5 · 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 Nanobrain · Jan 22, 2014 at 01:34 AM 0
Share

Very good idea Happymoo. props!

avatar image Rick74 · Jan 22, 2014 at 03:20 AM 0
Share

It's my understanding (And I could very well be wrong here) but timeScale = 0 globally stops time. $$anonymous$$eaning everything now stops. Even things like the UI or various other units or abilities or functions that I want you to access or have move, are all frozen as well. Which is why I've created my own time, and now have all units I want paused access that variable.

avatar image Nanobrain · Jan 22, 2014 at 04:37 AM 0
Share

As long as your functions don't make use of Time.deltaTime then I think you're okay. I don't think that the GUI makes use of Time.deltaTime either as referenced in Time.deltaTime's description:

Note that you should not rely on Time.deltaTime from inside OnGUI since OnGUI can be called multiple times per frame

avatar image Rick74 · Jan 22, 2014 at 11:32 AM 0
Share

Allot of functions and features in NGUI use time.Time and time.DeltaTime. As well, I'm running smooth moves which also uses time.Time on animation playback. So characters and NGUI are both frozen in this instance should I globally timeScale to 0.

avatar image HappyMoo · Jan 22, 2014 at 06:20 PM 0
Share

if that's true, NGUI is using the system in a wrong way.

Also what nanobrain says. OnGUI is called multiple times per frame.

If I wanted to animate my GUI, I would use Time.realtimeSinceStartup to base my animations on

avatar image
0

Answer by Nanobrain · Jan 21, 2014 at 06:50 PM

What about wrapping the pausable objects inside an empty gameobject. Then, when the game is paused, by whatever method, you can then use the BroadcastMessage method of your empty gameobject to call the pause method of it's children.

 myEmptyGameObject.BroadcastMessage("Pause", null);
Comment
Add comment · Show 2 · 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 Rick74 · Jan 21, 2014 at 08:53 PM 0
Share

Pause objects could include and are not limited too bullets and enemies and player units, all which are instantiated as the game progresses.

Unfortunately, I think I'm stuck using GameObject.Find. I 'think' Find by .tag is probably the quickest?

avatar image nesis · Jan 22, 2014 at 02:20 PM 1
Share

For my purposes, I use this class to register pausable scripts (C#):

 using UnityEngine;
 using System.Collections;

 //delegate with function signature to match update methods to be replaced
 public delegate void EventHandler();

 public class PauseController : $$anonymous$$onoBehaviour {
     
     //the three events to track for a pausable object
     private static event EventHandler PausableUpdate; //normal every-frame updating when not paused
     private static event EventHandler PausableUpdate_OnPause; //called the first frame this gets paused
     private static event EventHandler PausableUpdate_OnUnpause; //called the first frame this gets unpaused
     
     //two variables needed for tracking pausing
     private static bool isPaused = false;
     private static bool wasPaused = false;
     
     private void Update () {
         //manual pause toggle in this class if desired (uncomment the next line to enable)
         if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.P)) isPaused = !isPaused;
         
         //if game was just paused, invoke all PausableUpdate_OnPauses...
         if ((!wasPaused) && isPaused) {
             wasPaused = true;
             PausableUpdate_OnPause.Invoke();
         }
         //if game was just unpaused, invoke all PausableUpdate_OnUnpauses...
         else if (wasPaused && (!isPaused)) {
             wasPaused = false;
             PausableUpdate_OnUnpause.Invoke();
         }
         
         //if game isn't paused, invoke all PausableUpdates
         if (!isPaused) {
             PausableUpdate.Invoke();
         }
     }
     
     /// <summary>
     /// For objects that need to save and load state just before and after a pause
     /// (eg GameObjects with a Rigidbody component)
     /// </summary>
     /// <param name='methodToCallOnUpdate'>
     /// $$anonymous$$ethod to call on update.
     /// </param>
     /// <param name='methodToCallOnPause'>
     /// $$anonymous$$ethod to call on pause.
     /// </param>
     /// <param name='methodToCallOnUnpause'>
     /// $$anonymous$$ethod to call on unpause.
     /// </param>
     public static void RegisterUpdate(EventHandler methodToCallOnUpdate, EventHandler methodToCallOnPause, EventHandler methodToCallOnUnpause) {
         PausableUpdate += methodToCallOnUpdate;
         PausableUpdate_OnPause += methodToCallOnPause;
         PausableUpdate_OnUnpause += methodToCallOnUnpause;
     }
     
     /// <summary>
     /// For scripts that don't need to save and load state just before and after a pause.
     /// (should be most scripts)
     /// </summary>
     /// <param name='methodToCallOnUpdate'>
     /// $$anonymous$$ethod to call on update.
     /// </param>
     public static void RegisterUpdate(EventHandler methodToCallOnUpdate) {
         PausableUpdate += methodToCallOnUpdate;
     }
     
     //used for pausing, called by writing PauseController.Pause();
     public static void Pause() {
         isPaused = true;
     }
     
     //used for unpausing, called by writing PauseController.Unpause();
     public static void Unpause() {
         isPaused = false;
     }
     
     //used for checking if the game is paused, called by writing PauseController.IsPaused();
     public static bool IsPaused() {
         return isPaused;
     }
 }

(continued next post)

avatar image
0

Answer by nesis · Jan 22, 2014 at 02:24 PM

Then, using the PausableObject class, I can register some methods in another script to be called just like they're the normal Update() method, with the benefit of being pausable.

For example, a script that constantly rotates an object:

 using UnityEngine;
 using System.Collections;

 public class ConstantRotate : MonoBehaviour {
     
     private bool oldIsSleeping = false;
     private Vector3 oldVelocity;
     private Vector3 oldAngularMomentum;
     
     public void Start() {
         //Register some methods from this script to be called by PauseController
         //IMPORTANT: Do NOT use Update(), FixedUpdate(), or any of the other 
         //default update methods... If you do, during each frame, they'll get 
         //called twice - once by PauseController, then once by Unity! Write your
         //own method names, but other than that pretend they're the same as 
         //the default update methods.
         PauseController.RegisterUpdate(MyUpdate,OnPause,OnUnpause);
         
         //For a script without a rigidbody attached to its GameObject, you can 
         //just use:
         //PauseController.RegisterUpdate(MyUpdate);
     }
     
     public void OnPause() {
         if (!rigidbody) return;
         if (rigidbody.IsSleeping()) oldIsSleeping = true;
         else {
             oldVelocity = rigidbody.velocity;
             oldAngularMomentum = rigidbody.angularVelocity;
             rigidbody.Sleep();
             oldIsSleeping = false;
         }
     }
     
     public void OnUnpause() {
         if (!rigidbody) return;
         if (!oldIsSleeping) {
             rigidbody.WakeUp();
             rigidbody.velocity = oldVelocity;
             rigidbody.angularVelocity = oldAngularMomentum;
         }
     }
     
     public void MyUpdate() {
         transform.rotation = transform.rotation * Quaternion.Euler(0f,10f*Time.deltaTime,0f);
     }
 }

Note that rigidbodies need special treatment during pausing / unpausing. This is something I hope the Unity devs will fix in the future, but for now this workaround using OnPause / OnUnpause methods works just fine (as long as nothing bumps into the rigidbody during the pause, of course - that'd make it wake up, and potentially start moving again... so to handle that, you'd need to destroy the rigidbody during OnPause then re-create it during OnUnpause with all its original properties saved and re-loaded).

Comment
Add comment · Show 6 · 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 Rick74 · Jan 22, 2014 at 05:32 PM 0
Share

Thanks nesis, it'll take me a bit to take a look at all this because I'm not well versed in C# only javascript. For your rigid bodies problem, couldn't you just enable/disable collision or the triggers?

avatar image nesis · Jan 23, 2014 at 01:58 AM 0
Share

If you want non-pausable things to collide with those rigidbody colliders during a pause, then disabling the collider isn't a viable solution.

The ideal scenario (that Unity doesn't currently offer) would be to disable a rigidbody, save its member variables somewhere, and keep its collider enabled so things can bump into it (but not knock it around since it wouldn't have its rigidbody enabled). Then when re-enabling the rigidbody, set its member variables to what they were before it was disabled.

Really what you do with the paused rigidbodies depends on what you reasonably expect to happen to them while they're paused.

avatar image Rick74 · Jan 23, 2014 at 08:38 PM 0
Share

I'm still thinking about a cleaner way to do this.

Couldn't you just do the array method? Have each and any object that can be paused operate under a boolean;

 if (!paused)
 {
     Do what I'm supposed to do;
 }

Then have your master script create an array the moment the player hits pause

 pausedObjects [] = GameObjects.FindByTag ("objects I want paused");
 
 pausedObjects.Broadcast$$anonymous$$essage ("pause = true");
 

I'm sure I've messed up the syntax as I've never broadcast a message, but from my understanding, it sends a message to any object in an array regardless of script name?

If this method could work, how would I populate an array with FindByTag, but search for multiple tags?

avatar image Rick74 · Jan 23, 2014 at 10:09 PM 0
Share

Could you help me with the proper syntax Nano? I think I messed up a few things...

avatar image nesis · Jan 23, 2014 at 10:23 PM 0
Share

someGameObject.Broadcast$$anonymous$$essage("some$$anonymous$$ethod") calls a method called some$$anonymous$$ethod() in any script attached to someGameObject. I don't think there's a way to find multiple objects by multiple tags in one method call, so you should make an array of tag strings, then iterate over that, collecting all objects in a list.

Show more comments

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

22 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Detect when user minimizes application 3 Answers

A Proper Way To Pause A Game 9 Answers

I am creating a pause button and when I click it the score keeps rising. How can I stop it? 1 Answer

OnMouseDown not firing 2 Answers

show pause menu issues 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