Pro_Unit

Simulation

Nov 30th, 2020
374
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5.  
  6. namespace Platformer.Core
  7. {
  8.     /// <summary>
  9.     /// The Simulation class implements the discrete event simulator pattern.
  10.     /// Events are pooled, with a default capacity of 4 instances.
  11.     /// </summary>
  12.     public static partial class Simulation
  13.     {
  14.  
  15.         static HeapQueue<Event> eventQueue = new HeapQueue<Event>();
  16.         static Dictionary<System.Type, Stack<Event>> eventPools = new Dictionary<System.Type, Stack<Event>>();
  17.  
  18.         /// <summary>
  19.         /// Create a new event of type T and return it, but do not schedule it.
  20.         /// </summary>
  21.         /// <typeparam name="T"></typeparam>
  22.         /// <returns></returns>
  23.         static public T New<T>() where T : Event, new()
  24.         {
  25.             Stack<Event> pool;
  26.             if (!eventPools.TryGetValue(typeof(T), out pool))
  27.             {
  28.                 pool = new Stack<Event>(4);
  29.                 pool.Push(new T());
  30.                 eventPools[typeof(T)] = pool;
  31.             }
  32.             if (pool.Count > 0)
  33.                 return (T)pool.Pop();
  34.             else
  35.                 return new T();
  36.         }
  37.  
  38.         /// <summary>
  39.         /// Clear all pending events and reset the tick to 0.
  40.         /// </summary>
  41.         public static void Clear()
  42.         {
  43.             eventQueue.Clear();
  44.         }
  45.  
  46.         /// <summary>
  47.         /// Schedule an event for a future tick, and return it.
  48.         /// </summary>
  49.         /// <returns>The event.</returns>
  50.         /// <param name="tick">Tick.</param>
  51.         /// <typeparam name="T">The event type parameter.</typeparam>
  52.         static public T Schedule<T>(float tick = 0) where T : Event, new()
  53.         {
  54.             var ev = New<T>();
  55.             ev.tick = Time.time + tick;
  56.             eventQueue.Push(ev);
  57.             return ev;
  58.         }
  59.  
  60.         /// <summary>
  61.         /// Reschedule an existing event for a future tick, and return it.
  62.         /// </summary>
  63.         /// <returns>The event.</returns>
  64.         /// <param name="tick">Tick.</param>
  65.         /// <typeparam name="T">The event type parameter.</typeparam>
  66.         static public T Reschedule<T>(T ev, float tick) where T : Event, new()
  67.         {
  68.             ev.tick = Time.time + tick;
  69.             eventQueue.Push(ev);
  70.             return ev;
  71.         }
  72.  
  73.         /// <summary>
  74.         /// Return the simulation model instance for a class.
  75.         /// </summary>
  76.         /// <typeparam name="T"></typeparam>
  77.         static public T GetModel<T>() where T : class, new()
  78.         {
  79.             return InstanceRegister<T>.instance;
  80.         }
  81.  
  82.         /// <summary>
  83.         /// Set a simulation model instance for a class.
  84.         /// </summary>
  85.         /// <typeparam name="T"></typeparam>
  86.         static public void SetModel<T>(T instance) where T : class, new()
  87.         {
  88.             InstanceRegister<T>.instance = instance;
  89.         }
  90.  
  91.         /// <summary>
  92.         /// Destroy the simulation model instance for a class.
  93.         /// </summary>
  94.         /// <typeparam name="T"></typeparam>
  95.         static public void DestroyModel<T>() where T : class, new()
  96.         {
  97.             InstanceRegister<T>.instance = null;
  98.         }
  99.  
  100.         /// <summary>
  101.         /// Tick the simulation. Returns the count of remaining events.
  102.         /// If remaining events is zero, the simulation is finished unless events are
  103.         /// injected from an external system via a Schedule() call.
  104.         /// </summary>
  105.         /// <returns></returns>
  106.         static public int Tick()
  107.         {
  108.             var time = Time.time;
  109.             var executedEventCount = 0;
  110.             while (eventQueue.Count > 0 && eventQueue.Peek().tick <= time)
  111.             {
  112.                 var ev = eventQueue.Pop();
  113.                 var tick = ev.tick;
  114.                 ev.ExecuteEvent();
  115.                 if (ev.tick > tick)
  116.                 {
  117.                     //event was rescheduled, so do not return it to the pool.
  118.                 }
  119.                 else
  120.                 {
  121.                     // Debug.Log($"<color=green>{ev.tick} {ev.GetType().Name}</color>");
  122.                     ev.Cleanup();
  123.                     try
  124.                     {
  125.                         eventPools[ev.GetType()].Push(ev);
  126.                     }
  127.                     catch (KeyNotFoundException)
  128.                     {
  129.                         //This really should never happen inside a production build.
  130.                         Debug.LogError($"No Pool for: {ev.GetType()}");
  131.                     }
  132.                 }
  133.                 executedEventCount++;
  134.             }
  135.             return eventQueue.Count;
  136.         }
  137.     }
  138. }
  139.  
  140.  
  141.  
RAW Paste Data