Advertisement
mvaganov

StopTime.cs

May 10th, 2019
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.35 KB | None | 0 0
  1. using UnityEngine;
  2.  
  3. // A utility script to pause and unpause active elements in a Unity game
  4. // author: mvaganov@hotmail.com
  5. // license: Copyfree, public domain. This is free code! Great artists, steal this code!
  6. // latest version at: https://pastebin.com/raw/a79HvqbQ
  7. // designed to work with Timer: https://pastebin.com/raw/h61nAC3E
  8. public class StopTime : MonoBehaviour {
  9.     private interface IUnfreezable {
  10.         void Unfreeze();
  11.         bool IsUnfreezable();
  12.         object GetFrozen();
  13.     }
  14.     private class StasisPhysics : IUnfreezable {
  15.         public Rigidbody rb;
  16.         public Vector3 v, av;
  17.         public bool useGravity, isKinematic;
  18.         public StasisPhysics(Rigidbody rb){
  19.             this.rb = rb;
  20.             v = rb.velocity;
  21.             av = rb.angularVelocity;
  22.             useGravity = rb.useGravity;
  23.             isKinematic = rb.isKinematic;
  24.             rb.velocity = rb.angularVelocity = Vector3.zero;
  25.             rb.isKinematic=true;
  26.             rb.useGravity = false;
  27.         }
  28.         public bool IsUnfreezable() { return rb != null; }
  29.         public object GetFrozen() { return rb; }
  30.         public void Unfreeze() {
  31.             rb.velocity = v;
  32.             rb.angularVelocity = av;
  33.             rb.useGravity = useGravity;
  34.             rb.isKinematic = isKinematic;
  35.         }
  36.     }
  37.     private class StasisAnimation : IUnfreezable {
  38.         public Animation a;
  39.         public float speed;
  40.         public StasisAnimation(Animation a){
  41.             this.a = a;
  42.             speed = a[a.clip.name].speed;
  43.             a[a.clip.name].speed = 0;
  44.         }
  45.         public bool IsUnfreezable() { return a != null; }
  46.         public object GetFrozen() { return a; }
  47.         public void Unfreeze() { a[a.clip.name].speed = speed; }
  48.     }
  49.     private class StasisParticle : IUnfreezable {
  50.         public ParticleSystem ps;
  51.         public StasisParticle(ParticleSystem ps){ this.ps = ps; ps.Pause(); }
  52.         public bool IsUnfreezable() { return ps != null; }
  53.         public object GetFrozen() { return ps; }
  54.         public void Unfreeze() { ps.Play(); }
  55.     }
  56.     private class StasisAudioSource : IUnfreezable {
  57.         public AudioSource asrc;
  58.         public StasisAudioSource(AudioSource asrc){ this.asrc = asrc; asrc.Pause(); }
  59.         public bool IsUnfreezable() { return asrc != null; }
  60.         public object GetFrozen() { return asrc; }
  61.         public void Unfreeze() { asrc.Play(); }
  62.     }
  63.  
  64.     /// <summary>list of frozen things, saved before the objects are halted.</summary>
  65.     private static IUnfreezable[] snapshot = null;
  66.  
  67.     /// <returns><c>true</c> if the physics is frozen; otherwise, <c>false</c>.</returns>
  68.     public static bool IsStopped() { return snapshot != null; }
  69.  
  70.     public void ToggleTime() { Toggle (); }
  71.  
  72.     private static void SetChronoPaused(bool paused) {
  73.         object chrono_t = GetType("NS.Chrono");
  74.         if(chrono_t != null) {
  75.             System.Type t = chrono_t as System.Type;
  76.             System.Reflection.MethodInfo m = t.GetMethod("Instance");
  77.             object chrono = m.Invoke(null, new object[0]);
  78.  
  79.             NS.Chrono.Instance().paused = paused;
  80.         }
  81.     }
  82.  
  83.     public void disableTime() {
  84.         SetupIfNeeded();
  85.         whenDeactivates.Invoke ();
  86.         DisableTime ();
  87.     }
  88.     public static void DisableTime() {
  89.         SetChronoPaused(true);
  90.         Rigidbody[] bodies = FindObjectsOfType<Rigidbody> ();
  91.         Animation[] anims = FindObjectsOfType<Animation> ();
  92.         ParticleSystem[] particles = FindObjectsOfType<ParticleSystem>();
  93.         AudioSource[] audios = FindObjectsOfType<AudioSource>();
  94.         snapshot = new IUnfreezable[bodies.Length+anims.Length+ particles.Length+audios.Length];
  95.         int index = 0;
  96.         System.Array.ForEach(bodies, o => snapshot[index++] = new StasisPhysics(o));
  97.         System.Array.ForEach(anims, o => snapshot[index++] = new StasisAnimation(o));
  98.         System.Array.ForEach(particles, o => snapshot[index++] = new StasisParticle(o));
  99.         System.Array.ForEach(audios, o => snapshot[index++] = new StasisAudioSource(o));
  100.     }
  101.     public void enableTime() {
  102.         SetupIfNeeded ();
  103.         whenActivates.Invoke ();
  104.         EnableTime ();
  105.     }
  106.     public static void EnableTime() {
  107.         SetChronoPaused(false);
  108.         System.Array.ForEach(snapshot, (o) => { if(o.IsUnfreezable()) { o.Unfreeze(); } });
  109.         snapshot = null;
  110.     }
  111.  
  112.     /// Toggles time.
  113.     public static void Toggle() {
  114.         if (IsStopped ()) { EnableTime (); } else { DisableTime (); }
  115.     }
  116.     #region find-and-disable classes
  117.     public static System.Type GetType( string typeName ) {
  118.         // Try Type.GetType() first. This will work with types defined by the Mono runtime, in the same assembly as the caller, etc.
  119.         System.Type type = System.Type.GetType( typeName );
  120.         // If it worked, then we're done here
  121.         if( type != null ) return type;
  122.         // If we still haven't found the proper type, we can enumerate all of the loaded assemblies and see if any of them define the type
  123.         try{
  124.             var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
  125.             var referencedAssemblies = currentAssembly.GetReferencedAssemblies();
  126.             foreach( var assemblyName in referencedAssemblies ) {
  127.                 // Load the referenced assembly
  128.                 var assembly = System.Reflection.Assembly.Load( assemblyName );
  129.                 if( assembly != null ) {
  130.                     // See if that assembly defines the named type
  131.                     type = assembly.GetType( typeName );
  132.                     if( type != null ) return type;
  133.                 }
  134.             }
  135.         } catch (System.Exception){ }
  136.         // if the GetExecutingAssembly library call failed, possibly due to security constraints, try each known assembly individually
  137.         System.Reflection.Assembly[] assemblies = System.AppDomain.CurrentDomain.GetAssemblies ();
  138.         for (int i = 0; i < assemblies.Length; ++i) {
  139.             type = assemblies [i].GetType (typeName);
  140.             if (type != null) return type;
  141.         }
  142.         // If the TypeName is a full name in an un-loaded assembly, then we can try loading the defining assembly directly
  143.         if( typeName.Contains( "." ) ) {
  144.             try{
  145.                 // Get the name of the assembly (Assumption is that we are using fully-qualified type names)
  146.                 var assemblyName = typeName.Substring( 0, typeName.IndexOf( '.' ) );
  147.                 // Attempt to load the indicated Assembly
  148.                 var assembly = System.Reflection.Assembly.Load( assemblyName );
  149.                 if( assembly == null ) return null;
  150.                 // Ask that assembly to return the proper Type
  151.                 type = assembly.GetType( typeName );
  152.                 if( type != null ) return type;
  153.             }catch(System.Exception ){}
  154.         }
  155.         // The type just couldn't be found...
  156.         return null;
  157.     }
  158.  
  159.     [ContextMenuItem("connect to Timer","ConnectToTimer"), Tooltip("Will search for a MonoBehaviours with the given complete name to disable.")]
  160.     public string[] classTypesToToggle = new string[] {
  161.         "UnityStandardAssets.Characters.FirstPerson.FirstPersonController",
  162.         "UnityStandardAssets.Characters.FirstPerson.RigidbodyFirstPersonController"
  163.     };
  164.     private System.Type[] knownTypes;
  165.     [Tooltip("When time re-activates.")]
  166.     public UnityEngine.Events.UnityEvent whenActivates;
  167.     [Tooltip("When time de-activates.")]
  168.     public UnityEngine.Events.UnityEvent whenDeactivates;
  169.     private bool connectedToTimer = false;
  170.  
  171.     private void ConnectToTimer() {
  172.         NS.Chrono c = NS.Chrono.Instance();
  173.         if(c.onPause == null) c.onPause = new UnityEngine.Events.UnityEvent();
  174.         if(c.onUnpause == null) c.onUnpause = new UnityEngine.Events.UnityEvent();
  175.         c.onPause.AddListener(disableTime);
  176.         c.onUnpause.AddListener(enableTime);
  177.         connectedToTimer = true;
  178.     }
  179.  
  180.     private void SetupIfNeeded() {
  181.         if (knownTypes == null) { Setup (); }
  182.     }
  183.     private void Start() { SetupIfNeeded(); }
  184.     private void Setup () {
  185.         knownTypes = null;
  186.         for (int i = 0; i < classTypesToToggle.Length; ++i) {
  187.             System.Type t = GetType(classTypesToToggle[i]);
  188.             if (t != null) {
  189.                 if (knownTypes == null) {
  190.                     knownTypes = new System.Type[classTypesToToggle.Length];
  191.                 }
  192.                 knownTypes [i] = t;
  193.             }
  194.         }
  195.         if (knownTypes != null) {
  196.             whenActivates.AddListener(()=>{SetEnabled (true);});
  197.             whenDeactivates.AddListener(()=>{SetEnabled (false);});
  198.         }
  199.         if(!connectedToTimer) { ConnectToTimer(); }
  200.     }
  201.     private void SetEnabledAllBehavioursOfType(System.Type type, bool a_enabled) {
  202.         if (type == null) return;
  203.         Object[] objs = FindObjectsOfType (type);
  204.         for (int o = 0; o < objs .Length; ++o) {
  205.             Behaviour b = objs [o] as Behaviour;
  206.             if (b != null) {
  207.                 b.enabled = a_enabled;
  208.             }
  209.         }
  210.     }
  211.     public static void SetEnableMouse(bool a_enabled) {
  212.         Cursor.visible = !a_enabled;
  213.         Cursor.lockState = a_enabled ? CursorLockMode.Locked : CursorLockMode.None;
  214.     }
  215.     private void SetEnabled(bool a_enabled) {
  216.         if (knownTypes != null) {
  217.             for (int i = 0; i < knownTypes.Length; ++i) {
  218.                 if (knownTypes [i] != null) {
  219.                     SetEnabledAllBehavioursOfType (knownTypes [i], a_enabled);
  220.                 }
  221.             }
  222.         }
  223.         SetEnableMouse (a_enabled);
  224.     }
  225.     #endregion // find-and-disable classes
  226. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement