Created
December 3, 2021 09:23
-
-
Save LukasFratzl/a0faa1d6c044c50b8de36df76b21acb1 to your computer and use it in GitHub Desktop.
A example of Allocating and resizing NativeArrays generic with Reflection in Unity c# Jobs | DOTS
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
| public class AllocatingNativeArrayWithReflection : MonoBehaviour | |
| { | |
| protected virtual void AllocateCharacters(ref CharacterMotorJobs job, int length) | |
| { | |
| HandleArraysAll(ref job._motorJob, ArrayAction.ADD, length, new int[0]); | |
| } | |
| protected virtual void DisposeCharacters(ref CharacterMotorJobs job, int[] indexesToRemove) | |
| { | |
| HandleArraysAll(ref job._motorJob, ArrayAction.REMOVE, 0, indexesToRemove); | |
| } | |
| protected virtual void DisposeAllCharacters(ref CharacterMotorJobs job) | |
| { | |
| HandleArraysAll(ref job._motorJob, ArrayAction.DISPOSE, 0, new int[0]); | |
| } | |
| public enum ArrayAction | |
| { | |
| ADD, | |
| REMOVE, | |
| DISPOSE | |
| } | |
| protected void HandleArraysAll(ref SR_Motor.MotorJob job, ArrayAction _action, int countToAdd, int[] indexToRemove) | |
| { | |
| int currentCount = CharactersInScene.Count; | |
| indexToRemove = indexToRemove.ToList().OrderBy(x => x).ToArray(); // NEEDS TO REMOVE ORDERED BECAUSE SOMETIMES INDEXES ARE LOWER WHICH RESULT A REMOVE OF THE LOWER INDEX AND IF THE NEXT WOULD BE THE LAST IT'S OUT OF RANGE, SO WE START WITH THE HIGHEST INDEX IN THE "HandleArray" REMOVE METHOD | |
| HandleJob(ref job, currentCount, _action, indexToRemove, countToAdd); | |
| } | |
| protected void HandleJob<T>(ref T job, int _currentCount, ArrayAction _action, int[] _indexesToRemove = default, int _valuesCountToAdd = 0) where T : struct | |
| { | |
| Type type = job.GetType(); | |
| System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.DeclaredOnly; | |
| System.Reflection.FieldInfo[] finfos = type.GetFields(flags); | |
| object boxed = job; | |
| for (int f = 0; f < finfos.Length; f++) | |
| { | |
| object v = finfos[f].GetValue(boxed); | |
| bool changed = false; | |
| if (v != null) | |
| { | |
| changed = HandleField<int>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<bool>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<float>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<float3>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<quaternion>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<float2>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<Quaternion>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<sbyte>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<byte>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<int2>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<int3>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<Vector2>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<Vector3>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<Vector2Int>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| changed = HandleField<Vector3Int>(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); | |
| if (changed) { finfos[f].SetValue(boxed, v); continue; } | |
| } | |
| } | |
| job = (T)boxed; | |
| } | |
| protected bool HandleField<U>(ref object value, int _currentCount, ArrayAction _action, int[] _indexesToRemove = default, int _valuesCountToAdd = 0) where U : struct | |
| { | |
| bool hasChanged = false; | |
| if (value is NativeArray<U>) | |
| { | |
| var v = (NativeArray<U>)value; | |
| if (v != null) { hasChanged = true; HandleArray(ref v, _currentCount, _action, _indexesToRemove, _valuesCountToAdd); } | |
| if (hasChanged) value = v; | |
| } | |
| return hasChanged; | |
| } | |
| protected void HandleArray<T>(ref NativeArray<T> array, int _currentCount, ArrayAction _action, int[] _indexesToRemove = default, int _valuesCountToAdd = 0) where T : struct | |
| { | |
| if (_action == ArrayAction.ADD && _valuesCountToAdd > 0) AddItemsToNativeArray(ref array, _valuesCountToAdd); | |
| else if (_action == ArrayAction.REMOVE) DisposeArrayItems(ref array, _currentCount, _indexesToRemove); | |
| else if (_action == ArrayAction.DISPOSE) DisposeArray(ref array); | |
| } | |
| protected void DisposeArrayItems<T>(ref NativeArray<T> array, int _currentCount, int[] _indexesToRemove) where T : struct | |
| { | |
| if (_currentCount == 0 && array.IsCreated) DisposeArray(ref array); | |
| else if (_currentCount != 0 && array.IsCreated) RemoveItemsToNativeArrayAtIndexes(ref array, _indexesToRemove); | |
| } | |
| protected void DisposeArray<T>(ref NativeArray<T> array) where T : struct | |
| { | |
| if (array.IsCreated) array.Dispose(); | |
| } | |
| protected void AddItemsToNativeArray<T>(ref NativeArray<T> array, T[] items) where T : struct | |
| { | |
| T[] oldItems = array.IsCreated == false ? new T[0] : array.ToArray(); | |
| if (array.IsCreated) { DisposeArray(ref array); } | |
| var listItems = oldItems.ToList(); | |
| listItems.AddRange(items); | |
| array = new NativeArray<T>(listItems.ToArray(), Allocator.Persistent); | |
| } | |
| protected void AddItemsToNativeArray<T>(ref NativeArray<T> array, int items) where T : struct | |
| { | |
| T[] oldItems = array.IsCreated == false ? new T[0] : array.ToArray(); | |
| if (array.IsCreated) { DisposeArray(ref array); } | |
| var listItems = oldItems.ToList(); | |
| listItems.AddRange(new T[items]); | |
| array = new NativeArray<T>(listItems.ToArray(), Allocator.Persistent); | |
| } | |
| protected void RemoveItemsToNativeArrayAtIndexes<T>(ref NativeArray<T> array, int[] indexesOrdered) where T : struct | |
| { | |
| if (array.IsCreated == false) return; | |
| T[] oldItems = array.ToArray(); | |
| array.Dispose(); | |
| var listItems = oldItems.ToList(); | |
| for (int i = indexesOrdered.Length - 1; i >= 0; i--) // REVERSE LOOP TO START WITH THE HIGHEST INDEX | |
| { | |
| if (i < listItems.Count) listItems.RemoveAt(indexesOrdered[i]); | |
| } | |
| array = new NativeArray<T>(listItems.ToArray(), Allocator.Persistent); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment