Advertisement
mvaganov

StopTime.cs

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