Last active
April 12, 2021 18:28
-
-
Save margaretdax/7815bcbba5dfe1dd3d75cc0b823dfeec to your computer and use it in GitHub Desktop.
Example implementation of an abstraction to "simply" implement object pooling for compiler generated IEnumerator state machines. Makes use of goto and requires a great deal of usage dicipline. Not ideal but for those applications that can't tollerate IEnumerator GC/alloc costs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using Zenject; | |
public abstract class PooledEnumerator<T> : IDisposable, IEnumerator where T : PooledEnumerator<T>, new() | |
{ | |
private static readonly StaticMemoryPool<T> Pool = new StaticMemoryPool<T>(); | |
// ReSharper disable once StaticMemberInGenericType | |
private static readonly object CompletedSignal = new object(); | |
private IEnumerator iterator; | |
private T self; | |
private bool interrupted; | |
protected bool Interrupted => interrupted; | |
protected static T Create() | |
{ | |
T spawned = Pool.Spawn(); | |
spawned.self = spawned; | |
return spawned; | |
} | |
private static void Destroy(T obj) | |
{ | |
// Signal to Run that it might need to Restart | |
obj.interrupted = true; | |
Pool.Despawn(obj); | |
} | |
public void Dispose() | |
{ | |
Destroy(self); | |
} | |
protected abstract IEnumerator Impl(); | |
protected object Completed() | |
{ | |
return CompletedSignal; | |
} | |
public bool MoveNext() | |
{ | |
if (iterator == null) | |
{ | |
interrupted = false; | |
iterator = Impl(); | |
} | |
if(iterator != null && iterator.MoveNext()) | |
{ | |
interrupted = false; | |
if (iterator.Current != CompletedSignal) return true; | |
} | |
Pool.Despawn(self); | |
return false; | |
} | |
public void Reset() | |
{ | |
throw new System.NotImplementedException(); | |
} | |
public object Current => iterator?.Current; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public static class Routine | |
{ | |
// Every time Move() is called codegen generates garbage | |
// public static IEnumerator Move(Transform trans, Vector3 target, float rate = 0.3f) | |
// { | |
// Vector3 pos = trans.localPosition; | |
// while ((target - pos).sqrMagnitude > 0.1f) | |
// { | |
// pos = Vector2.Lerp(pos, target, Lerp(rate)); | |
// trans.localPosition = pos; | |
// yield return null; | |
// } | |
// trans.localPosition = target; | |
// } | |
// Calling Move doesn't generate garbage (must be Disposed if interrupted) | |
public static IEnumerator Move(Transform trans, Vector3 target, float rate = 0.3f) | |
{ | |
return MoveTransform.Create(trans, target, rate); | |
} | |
public class MoveTransform : PooledEnumerator<MoveTransform> | |
{ | |
private Transform trans; | |
private Vector3 target; | |
private float rate; | |
public static MoveTransform Create(Transform trans, Vector3 target, float rate = 0.3f) | |
{ | |
MoveTransform obj = Create(); | |
obj.trans = trans; | |
obj.target = target; | |
obj.rate = rate; | |
return obj; | |
} | |
protected override IEnumerator Impl() | |
{ | |
Restart: | |
Vector3 pos = trans.localPosition; | |
while ((target - pos).sqrMagnitude > 0.1f) | |
{ | |
pos = Vector2.Lerp(pos, target, Lerp(rate)); | |
trans.localPosition = pos; | |
yield return null; | |
if(Interrupted) goto Restart; | |
} | |
trans.localPosition = target; | |
yield return Completed(); | |
goto Restart; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment