com.wallstop-studios.unity-helpers 2.0.0-rc39 → 2.0.0-rc41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/.github/workflows/npm-publish.yml +22 -26
  2. package/Editor/AnimationCopier.cs +25 -2
  3. package/Editor/AnimationCreator.cs +18 -27
  4. package/Editor/AnimatorControllerCopier.cs +7 -7
  5. package/Editor/EnsureTextureSizeWizard.cs +14 -9
  6. package/Editor/PrefabCheckWizard.cs +1 -1
  7. package/Editor/Utils/{ReadOnlyPropertyDrawer.cs → DxReadOnlyPropertyDrawer.cs} +2 -2
  8. package/README.md +37 -1
  9. package/Runtime/Core/Attributes/ChildComponentAttribute.cs +39 -19
  10. package/Runtime/Core/Attributes/DxReadOnlyAttribute.cs +6 -0
  11. package/Runtime/Core/Attributes/ParentComponent.cs +16 -15
  12. package/Runtime/Core/Attributes/SiblingComponentAttribute.cs +7 -9
  13. package/Runtime/Core/Helper/Partials/TransformHelpers.cs +26 -0
  14. package/Runtime/Core/Helper/ReflectionHelpers.cs +167 -22
  15. package/Tests/Runtime/Components/{RelationalComponentTester.cs → RelationalComponentTesterComplex.cs} +1 -1
  16. package/Tests/Runtime/Components/RelationalComponentsTesterSimple.cs +40 -0
  17. package/Tests/Runtime/Components/RelationalComponentsTesterSimple.cs.meta +3 -0
  18. package/Tests/Runtime/Helper/ReflectionHelperTests.cs +215 -0
  19. package/Tests/Runtime/Helper/ReflectionHelperTests.cs.meta +3 -0
  20. package/Tests/Runtime/Performance/RelationComponentPerformanceTests.cs +27 -3
  21. package/package.json +1 -1
  22. package/.github/workflows/unity-package.yml +0 -105
  23. package/Editor/BuildScript.cs +0 -33
  24. package/Editor/BuildScript.cs.meta +0 -3
  25. package/Editor/Scenes/SampleScene.unity +0 -221
  26. package/Editor/Scenes/SampleScene.unity.meta +0 -7
  27. package/Editor/Scenes.meta +0 -3
  28. package/Runtime/Core/Attributes/ReadOnlyAttribute.cs +0 -6
  29. /package/Editor/Utils/{ReadOnlyPropertyDrawer.cs.meta → DxReadOnlyPropertyDrawer.cs.meta} +0 -0
  30. /package/Runtime/Core/Attributes/{ReadOnlyAttribute.cs.meta → DxReadOnlyAttribute.cs.meta} +0 -0
  31. /package/Tests/Runtime/Components/{RelationalComponentTester.cs.meta → RelationalComponentTesterComplex.cs.meta} +0 -0
@@ -8,22 +8,20 @@
8
8
  using System.Runtime.CompilerServices;
9
9
  using Extension;
10
10
 
11
+ public delegate void FieldSetter<TInstance, in TValue>(ref TInstance instance, TValue value);
12
+
11
13
  public static class ReflectionHelpers
12
14
  {
13
15
  private static readonly Dictionary<Type, Func<int, Array>> ArrayCreators = new();
14
16
  private static readonly Dictionary<Type, Func<IList>> ListCreators = new();
15
17
  private static readonly Dictionary<Type, Func<int, IList>> ListWithCapacityCreators = new();
16
18
 
17
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
18
- public static Func<int, Array> GetOrCreateArrayCreator(Type type)
19
- {
20
- return ArrayCreators.GetOrAdd(type, elementType => GetArrayCreator(elementType));
21
- }
22
-
23
19
  [MethodImpl(MethodImplOptions.AggressiveInlining)]
24
20
  public static Array CreateArray(Type type, int length)
25
21
  {
26
- return GetOrCreateArrayCreator(type).Invoke(length);
22
+ return ArrayCreators
23
+ .GetOrAdd(type, elementType => GetArrayCreator(elementType))
24
+ .Invoke(length);
27
25
  }
28
26
 
29
27
  [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -40,32 +38,180 @@
40
38
  return ListCreators.GetOrAdd(elementType, type => GetListCreator(type)).Invoke();
41
39
  }
42
40
 
43
- public static Action<object, object> CreateFieldSetter(Type type, FieldInfo field)
41
+ public static Func<object, object> GetFieldGetter(FieldInfo field)
42
+ {
43
+ #if WEB_GL
44
+ return field.GetValue;
45
+ #else
46
+ DynamicMethod dynamicMethod = new(
47
+ $"Get{(field.DeclaringType?.Name ?? string.Empty)}{field.Name}",
48
+ typeof(object),
49
+ new[] { typeof(object) },
50
+ field.DeclaringType,
51
+ true
52
+ );
53
+
54
+ ILGenerator il = dynamicMethod.GetILGenerator();
55
+ il.Emit(OpCodes.Ldarg_0);
56
+ il.Emit(
57
+ field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
58
+ field.DeclaringType
59
+ );
60
+
61
+ il.Emit(OpCodes.Ldfld, field);
62
+
63
+ // If the field's type is a value type, box it.
64
+ if (field.FieldType.IsValueType)
65
+ {
66
+ il.Emit(OpCodes.Box, field.FieldType);
67
+ }
68
+
69
+ il.Emit(OpCodes.Ret);
70
+
71
+ return (Func<object, object>)dynamicMethod.CreateDelegate(typeof(Func<object, object>));
72
+ #endif
73
+ }
74
+
75
+ public static Func<TInstance, TValue> GetFieldGetter<TInstance, TValue>(FieldInfo field)
76
+ {
77
+ #if WEB_GL
78
+ return Getter;
79
+ TValue Getter(TInstance instance)
80
+ {
81
+ return (TValue)field.GetValue(instance);
82
+ }
83
+ #else
84
+ DynamicMethod dynamicMethod = new(
85
+ $"GetGeneric{field.DeclaringType.Name}{field.Name}",
86
+ typeof(TValue),
87
+ new[] { typeof(TInstance) },
88
+ field.DeclaringType,
89
+ true
90
+ );
91
+
92
+ ILGenerator il = dynamicMethod.GetILGenerator();
93
+
94
+ if (!field.IsStatic)
95
+ {
96
+ if (typeof(TInstance).IsValueType)
97
+ {
98
+ il.Emit(OpCodes.Ldarga_S, 0);
99
+ }
100
+ else
101
+ {
102
+ il.Emit(OpCodes.Ldarg_0);
103
+ }
104
+
105
+ if (field.DeclaringType != typeof(TInstance))
106
+ {
107
+ il.Emit(
108
+ field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
109
+ field.DeclaringType
110
+ );
111
+ }
112
+
113
+ il.Emit(OpCodes.Ldfld, field);
114
+ }
115
+ else
116
+ {
117
+ il.Emit(OpCodes.Ldsfld, field);
118
+ }
119
+
120
+ if (field.FieldType.IsValueType)
121
+ {
122
+ if (!typeof(TValue).IsValueType)
123
+ {
124
+ il.Emit(OpCodes.Box, field.FieldType);
125
+ }
126
+ }
127
+ else
128
+ {
129
+ if (typeof(TValue).IsValueType)
130
+ {
131
+ il.Emit(OpCodes.Unbox_Any, typeof(TValue));
132
+ }
133
+ else if (typeof(TValue) != field.FieldType)
134
+ {
135
+ il.Emit(OpCodes.Castclass, typeof(TValue));
136
+ }
137
+ }
138
+
139
+ il.Emit(OpCodes.Ret);
140
+ return (Func<TInstance, TValue>)
141
+ dynamicMethod.CreateDelegate(typeof(Func<TInstance, TValue>));
142
+ #endif
143
+ }
144
+
145
+ public static FieldSetter<TInstance, TValue> GetFieldSetter<TInstance, TValue>(
146
+ FieldInfo field
147
+ )
148
+ {
149
+ #if WEB_GL
150
+ return Setter;
151
+ void Setter(ref TInstance instance, TValue newValue)
152
+ {
153
+ object value = instance;
154
+ field.SetValue(value, newValue);
155
+ instance = (TInstance)value;
156
+ }
157
+ #else
158
+ Type instanceType = field.DeclaringType;
159
+ Type valueType = field.FieldType;
160
+
161
+ DynamicMethod dynamicMethod = new(
162
+ $"SetFieldGeneric{field.DeclaringType.Name}{field.Name}",
163
+ MethodAttributes.Public | MethodAttributes.Static,
164
+ CallingConventions.Standard,
165
+ typeof(void),
166
+ new[] { instanceType.MakeByRefType(), valueType },
167
+ field.Module,
168
+ true
169
+ );
170
+
171
+ ILGenerator il = dynamicMethod.GetILGenerator();
172
+ il.Emit(OpCodes.Ldarg_0);
173
+ if (!instanceType.IsValueType)
174
+ {
175
+ il.Emit(OpCodes.Ldind_Ref);
176
+ }
177
+
178
+ il.Emit(OpCodes.Ldarg_1);
179
+ il.Emit(OpCodes.Stfld, field);
180
+ il.Emit(OpCodes.Ret);
181
+
182
+ Type delegateType = typeof(FieldSetter<,>).MakeGenericType(instanceType, valueType);
183
+ return (FieldSetter<TInstance, TValue>)dynamicMethod.CreateDelegate(delegateType);
184
+ #endif
185
+ }
186
+
187
+ public static Action<object, object> GetFieldSetter(FieldInfo field)
44
188
  {
45
189
  #if WEB_GL
46
190
  return field.SetValue;
47
191
  #else
48
192
  DynamicMethod dynamicMethod = new(
49
- $"SetField{field.Name}",
193
+ $"SetField{field.DeclaringType.Name}{field.Name}",
50
194
  null,
51
195
  new[] { typeof(object), typeof(object) },
52
- type.Module,
196
+ field.DeclaringType.Module,
53
197
  true
54
198
  );
55
199
 
56
200
  ILGenerator il = dynamicMethod.GetILGenerator();
57
201
 
58
- il.Emit(OpCodes.Ldarg_0); // Load the object (arg0)
59
- il.Emit(OpCodes.Castclass, type); // Cast to the actual type
202
+ il.Emit(OpCodes.Ldarg_0);
203
+ il.Emit(
204
+ field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
205
+ field.DeclaringType
206
+ );
60
207
 
61
- il.Emit(OpCodes.Ldarg_1); // Load the value (arg1)
208
+ il.Emit(OpCodes.Ldarg_1);
62
209
  il.Emit(
63
210
  field.FieldType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
64
211
  field.FieldType
65
- ); // Cast for reference types
66
- // Unbox if it's a value type
67
- il.Emit(OpCodes.Stfld, field); // Set the field
68
- il.Emit(OpCodes.Ret); // Return
212
+ );
213
+ il.Emit(OpCodes.Stfld, field);
214
+ il.Emit(OpCodes.Ret);
69
215
  return (Action<object, object>)
70
216
  dynamicMethod.CreateDelegate(typeof(Action<object, object>));
71
217
  #endif
@@ -76,9 +222,8 @@
76
222
  #if WEB_GL
77
223
  return size => Array.CreateInstance(elementType, size);
78
224
  #else
79
-
80
- DynamicMethod dynamicMethod = new DynamicMethod(
81
- $"CreateArray{elementType.Namespace}",
225
+ DynamicMethod dynamicMethod = new(
226
+ $"CreateArray{elementType.Name}",
82
227
  typeof(Array), // Return type: Array
83
228
  new[] { typeof(int) }, // Parameter: int (size)
84
229
  true
@@ -98,7 +243,7 @@
98
243
  #if WEB_GL
99
244
  return () => (IList)Activator.CreateInstance(listType);
100
245
  #else
101
- DynamicMethod dynamicMethod = new DynamicMethod(
246
+ DynamicMethod dynamicMethod = new(
102
247
  $"CreateList{listType.Name}",
103
248
  typeof(IList), // Return type: IList
104
249
  Type.EmptyTypes, // No parameters
@@ -126,7 +271,7 @@
126
271
  #if WEB_GL
127
272
  return _ => (IList)Activator.CreateInstance(listType);
128
273
  #else
129
- DynamicMethod dynamicMethod = new DynamicMethod(
274
+ DynamicMethod dynamicMethod = new(
130
275
  $"CreateListWithCapacity{listType.Name}",
131
276
  typeof(IList), // Return type: IList
132
277
  new[] { typeof(int) }, // Parameter: int (size)
@@ -8,7 +8,7 @@
8
8
  [RequireComponent(typeof(BoxCollider2D))]
9
9
  [RequireComponent(typeof(BoxCollider2D))]
10
10
  [RequireComponent(typeof(PolygonCollider2D))]
11
- public sealed class RelationalComponentTester : MonoBehaviour
11
+ public sealed class RelationalComponentTesterComplex : MonoBehaviour
12
12
  {
13
13
  [SiblingComponent]
14
14
  internal SpriteRenderer _spriteRenderer;
@@ -0,0 +1,40 @@
1
+ namespace UnityHelpers.Tests.Components
2
+ {
3
+ namespace UnityHelpers.Tests.Components
4
+ {
5
+ using Core.Attributes;
6
+ using UnityEngine;
7
+
8
+ [DisallowMultipleComponent]
9
+ [RequireComponent(typeof(SpriteRenderer))]
10
+ [RequireComponent(typeof(BoxCollider2D))]
11
+ [RequireComponent(typeof(BoxCollider2D))]
12
+ [RequireComponent(typeof(PolygonCollider2D))]
13
+ public sealed class RelationalComponentTesterSimple : MonoBehaviour
14
+ {
15
+ [SiblingComponent]
16
+ internal SpriteRenderer _spriteRenderer;
17
+
18
+ [SiblingComponent]
19
+ internal Transform _transform;
20
+
21
+ [SiblingComponent]
22
+ internal PolygonCollider2D _polygonCollider;
23
+
24
+ // [ParentComponent]
25
+ // internal PolygonCollider2D _polygonColliderParent;
26
+
27
+ [SiblingComponent]
28
+ internal BoxCollider2D _boxCollider;
29
+
30
+ // [ParentComponent]
31
+ // internal BoxCollider2D _boxColliderParent;
32
+ //
33
+ // [ChildComponent]
34
+ // internal BoxCollider2D _boxColliderChild;
35
+ //
36
+ // [ChildComponent]
37
+ // internal BoxCollider2D _boxColliderParentChild;
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 56d8fae7976140d3b7eb031a8dfccdba
3
+ timeCreated: 1742094536
@@ -0,0 +1,215 @@
1
+ namespace UnityHelpers.Tests.Tests.Runtime.Helper
2
+ {
3
+ using System;
4
+ using System.Collections;
5
+ using System.Collections.Generic;
6
+ using Core.Helper;
7
+ using NUnit.Framework;
8
+
9
+ public struct TestStruct
10
+ {
11
+ public int intValue;
12
+ }
13
+
14
+ public sealed class TestClass
15
+ {
16
+ public int intValue;
17
+ }
18
+
19
+ public sealed class ReflectionHelperTests
20
+ {
21
+ internal const int NumTries = 1_000;
22
+
23
+ private readonly Random _random = new();
24
+
25
+ // TODO: Test on static fields
26
+ [Test]
27
+ public void GetFieldGetterClass()
28
+ {
29
+ TestClass testClass = new();
30
+ Func<object, object> classGetter = ReflectionHelpers.GetFieldGetter(
31
+ typeof(TestClass).GetField(nameof(TestClass.intValue))
32
+ );
33
+ Assert.AreEqual(testClass.intValue, classGetter(testClass));
34
+ for (int i = 0; i < NumTries; ++i)
35
+ {
36
+ testClass.intValue = _random.Next(int.MinValue, int.MaxValue);
37
+ Assert.AreEqual(testClass.intValue, classGetter(testClass));
38
+ }
39
+ }
40
+
41
+ // TODO: Test on static fields
42
+ [Test]
43
+ public void GetFieldGetterStruct()
44
+ {
45
+ TestStruct testStruct = new();
46
+ Func<object, object> structGetter = ReflectionHelpers.GetFieldGetter(
47
+ typeof(TestStruct).GetField(nameof(TestStruct.intValue))
48
+ );
49
+ Assert.AreEqual(testStruct.intValue, structGetter(testStruct));
50
+ for (int i = 0; i < NumTries; ++i)
51
+ {
52
+ testStruct.intValue = _random.Next(int.MinValue, int.MaxValue);
53
+ Assert.AreEqual(testStruct.intValue, structGetter(testStruct));
54
+ }
55
+ }
56
+
57
+ // TODO: Test on static fields
58
+ [Test]
59
+ public void GetFieldSetterClass()
60
+ {
61
+ TestClass testClass = new();
62
+ Action<object, object> structSetter = ReflectionHelpers.GetFieldSetter(
63
+ typeof(TestClass).GetField(nameof(TestClass.intValue))
64
+ );
65
+ for (int i = 0; i < NumTries; ++i)
66
+ {
67
+ int expected = _random.Next(int.MinValue, int.MaxValue);
68
+ structSetter(testClass, expected);
69
+ Assert.AreEqual(expected, testClass.intValue);
70
+ }
71
+ }
72
+
73
+ // TODO: Test on static fields
74
+ [Test]
75
+ public void GetFieldSetterStruct()
76
+ {
77
+ // Need boxing
78
+ object testStruct = new TestStruct();
79
+ Action<object, object> structSetter = ReflectionHelpers.GetFieldSetter(
80
+ typeof(TestStruct).GetField(nameof(TestStruct.intValue))
81
+ );
82
+ for (int i = 0; i < NumTries; ++i)
83
+ {
84
+ int expected = _random.Next(int.MinValue, int.MaxValue);
85
+ structSetter(testStruct, expected);
86
+ Assert.AreEqual(expected, ((TestStruct)testStruct).intValue);
87
+ }
88
+ }
89
+
90
+ // TODO: Test on static fields
91
+ [Test]
92
+ public void GetFieldSetterClassGeneric()
93
+ {
94
+ TestClass testClass = new();
95
+ FieldSetter<TestClass, int> classSetter = ReflectionHelpers.GetFieldSetter<
96
+ TestClass,
97
+ int
98
+ >(typeof(TestClass).GetField(nameof(TestClass.intValue)));
99
+ for (int i = 0; i < NumTries; ++i)
100
+ {
101
+ int expected = _random.Next(int.MinValue, int.MaxValue);
102
+ classSetter(ref testClass, expected);
103
+ Assert.AreEqual(expected, testClass.intValue);
104
+ }
105
+ }
106
+
107
+ // TODO: Test on static fields
108
+ [Test]
109
+ public void GetFieldSetterStructGeneric()
110
+ {
111
+ TestStruct testStruct = new();
112
+ FieldSetter<TestStruct, int> structSetter = ReflectionHelpers.GetFieldSetter<
113
+ TestStruct,
114
+ int
115
+ >(typeof(TestStruct).GetField(nameof(TestStruct.intValue)));
116
+ for (int i = 0; i < NumTries; ++i)
117
+ {
118
+ int expected = _random.Next(int.MinValue, int.MaxValue);
119
+ structSetter(ref testStruct, expected);
120
+ Assert.AreEqual(expected, testStruct.intValue);
121
+ }
122
+ }
123
+
124
+ // TODO: Test on static fields
125
+ [Test]
126
+ public void GetFieldGetterClassGeneric()
127
+ {
128
+ TestClass testClass = new();
129
+ Func<TestClass, int> classGetter = ReflectionHelpers.GetFieldGetter<TestClass, int>(
130
+ typeof(TestClass).GetField(nameof(TestClass.intValue))
131
+ );
132
+ for (int i = 0; i < NumTries; ++i)
133
+ {
134
+ testClass.intValue = _random.Next(int.MinValue, int.MaxValue);
135
+ Assert.AreEqual(testClass.intValue, classGetter(testClass));
136
+ }
137
+ }
138
+
139
+ // TODO: Test on static fields
140
+ [Test]
141
+ public void GetFieldGetterStructGeneric()
142
+ {
143
+ TestStruct testStruct = new();
144
+ Func<TestStruct, int> structSetter = ReflectionHelpers.GetFieldGetter<TestStruct, int>(
145
+ typeof(TestStruct).GetField(nameof(TestStruct.intValue))
146
+ );
147
+ for (int i = 0; i < NumTries; ++i)
148
+ {
149
+ testStruct.intValue = _random.Next(int.MinValue, int.MaxValue);
150
+ Assert.AreEqual(testStruct.intValue, structSetter(testStruct));
151
+ }
152
+ }
153
+
154
+ [Test]
155
+ public void ArrayCreator()
156
+ {
157
+ for (int i = 0; i < NumTries; ++i)
158
+ {
159
+ int count = _random.Next(1_000);
160
+ Array created = ReflectionHelpers.CreateArray(typeof(int), count);
161
+ Assert.AreEqual(count, created.Length);
162
+ Assert.IsTrue(created is int[]);
163
+ int[] typed = (int[])created;
164
+ Assert.AreEqual(count, typed.Length);
165
+ }
166
+ }
167
+
168
+ [Test]
169
+ public void ListCreator()
170
+ {
171
+ for (int i = 0; i < NumTries; ++i)
172
+ {
173
+ IList created = ReflectionHelpers.CreateList(typeof(int));
174
+ Assert.AreEqual(0, created.Count);
175
+ Assert.IsTrue(created is List<int>);
176
+ List<int> typedCreated = (List<int>)created;
177
+ int count = _random.Next(50);
178
+ List<int> expected = new();
179
+ for (int j = 0; j < count; ++j)
180
+ {
181
+ int element = _random.Next();
182
+ created.Add(element);
183
+ expected.Add(element);
184
+ Assert.AreEqual(j + 1, created.Count);
185
+ Assert.That(expected, Is.EqualTo(typedCreated));
186
+ }
187
+ }
188
+ }
189
+
190
+ [Test]
191
+ public void ListWithSizeCreator()
192
+ {
193
+ for (int i = 0; i < NumTries; ++i)
194
+ {
195
+ int capacity = _random.Next(1_000);
196
+ IList created = ReflectionHelpers.CreateList(typeof(int), capacity);
197
+ Assert.AreEqual(0, created.Count);
198
+ Assert.IsTrue(created is List<int>);
199
+ List<int> typedCreated = (List<int>)created;
200
+ Assert.AreEqual(capacity, typedCreated.Capacity);
201
+
202
+ int count = _random.Next(50);
203
+ List<int> expected = new();
204
+ for (int j = 0; j < count; ++j)
205
+ {
206
+ int element = _random.Next();
207
+ created.Add(element);
208
+ expected.Add(element);
209
+ Assert.AreEqual(j + 1, created.Count);
210
+ Assert.That(expected, Is.EqualTo(typedCreated));
211
+ }
212
+ }
213
+ }
214
+ }
215
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 727a306f7f144d758b6f6425b6a442ed
3
+ timeCreated: 1742157564
@@ -3,6 +3,7 @@
3
3
  using System;
4
4
  using System.Diagnostics;
5
5
  using Components;
6
+ using Components.UnityHelpers.Tests.Components;
6
7
  using Core.Attributes;
7
8
  using NUnit.Framework;
8
9
  using UnityEngine;
@@ -10,12 +11,13 @@
10
11
  public sealed class RelationComponentPerformanceTests
11
12
  {
12
13
  [Test]
13
- public void RelationalPerformanceTest()
14
+ public void RelationalPerformanceComplexTest()
14
15
  {
15
16
  int count = 0;
16
17
 
17
- GameObject go = new("Test", typeof(RelationalComponentTester));
18
- RelationalComponentTester tester = go.GetComponent<RelationalComponentTester>();
18
+ GameObject go = new("Test", typeof(RelationalComponentTesterComplex));
19
+ RelationalComponentTesterComplex tester =
20
+ go.GetComponent<RelationalComponentTesterComplex>();
19
21
  // Pre-warm
20
22
  tester.AssignRelationalComponents();
21
23
 
@@ -33,5 +35,27 @@
33
35
  Assert.AreNotEqual(0, tester._parentColliders.Length);
34
36
  Assert.AreNotEqual(0, tester._siblingColliders.Length);
35
37
  }
38
+
39
+ [Test]
40
+ public void RelationalPerformanceSimpleTest()
41
+ {
42
+ int count = 0;
43
+
44
+ GameObject go = new("Test", typeof(RelationalComponentTesterSimple));
45
+ RelationalComponentTesterSimple tester =
46
+ go.GetComponent<RelationalComponentTesterSimple>();
47
+ // Pre-warm
48
+ tester.AssignRelationalComponents();
49
+
50
+ TimeSpan timeout = TimeSpan.FromSeconds(10);
51
+ Stopwatch timer = Stopwatch.StartNew();
52
+ do
53
+ {
54
+ tester.AssignRelationalComponents();
55
+ ++count;
56
+ } while (timer.Elapsed < timeout);
57
+
58
+ UnityEngine.Debug.Log($"Averaged {count / timeout.TotalSeconds} operations / second.");
59
+ }
36
60
  }
37
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.wallstop-studios.unity-helpers",
3
- "version": "2.0.0-rc39",
3
+ "version": "2.0.0-rc41",
4
4
  "displayName": "Unity Helpers",
5
5
  "description": "Various Unity Helper Library",
6
6
  "dependencies": {},
@@ -1,105 +0,0 @@
1
- name: Export and Release Unity Package
2
-
3
- on:
4
- workflow_run:
5
- workflows: ["Unity Tests"]
6
- types:
7
- - completed
8
- workflow_dispatch:
9
- inputs:
10
- logLevel:
11
- description: 'Log level'
12
- required: true
13
- default: 'warning'
14
- environment:
15
- description: 'Environment to deploy'
16
- required: false
17
- default: 'staging'
18
-
19
- env:
20
- UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
21
-
22
- jobs:
23
- package_unity:
24
- runs-on: ubuntu-latest
25
-
26
- steps:
27
- - name: Checkout Repository
28
- uses: actions/checkout@v4
29
- with:
30
- fetch-depth: 0 # Ensure full commit history for version comparison
31
-
32
- - name: Set up Node.js
33
- uses: actions/setup-node@v4
34
- with:
35
- node-version: 18
36
-
37
- - name: Check if version changed
38
- id: version_check
39
- run: |
40
- PREV_VERSION=$(git show HEAD~1:package.json | jq -r '.version' || echo "0.0.0")
41
- NEW_VERSION=$(jq -r '.version' package.json)
42
- echo "Previous version: $PREV_VERSION"
43
- echo "New version: $NEW_VERSION"
44
-
45
- if [ "$PREV_VERSION" != "$NEW_VERSION" ]; then
46
- echo "Version changed, proceeding..."
47
- echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
48
- echo "should_build=true" >> $GITHUB_ENV
49
-
50
- # Check for pre-release versions
51
- if [[ "$NEW_VERSION" == *"rc"* ]]; then
52
- echo "This is a pre-release (next tag)."
53
- echo "IS_PRERELEASE=true" >> $GITHUB_ENV
54
- else
55
- echo "This is a stable release."
56
- echo "IS_PRERELEASE=false" >> $GITHUB_ENV
57
- fi
58
- else
59
- echo "Version did not change, skipping..."
60
- echo "should_build=false" >> $GITHUB_ENV
61
- fi
62
-
63
- - name: Set up Unity
64
- if: env.should_build == 'true'
65
- uses: game-ci/unity-builder@v4
66
- env:
67
- UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
68
- UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
69
- UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
70
- with:
71
- unityVersion: 2022.3.5f1
72
- targetPlatform: StandaloneLinux64
73
- buildMethod: BuildScript.BuildLinux
74
- projectPath: .
75
-
76
- - name: Export Unity Package
77
- if: env.should_build == 'true'
78
- run: |
79
- EXPORT_DIR="UnityHelpers"
80
- PACKAGE_NAME="WallstopStudios.UnityHelpers.unitypackage"
81
-
82
- mkdir -p $EXPORT_DIR
83
-
84
- echo "Exporting package: $EXPORT_DIR/$PACKAGE_NAME"
85
-
86
- /opt/unity/Editor/Unity \
87
- -batchmode -quit \
88
- -projectPath "$(pwd)" \
89
- -exportPackage "Assets" "$EXPORT_DIR/$PACKAGE_NAME"
90
-
91
- echo "PACKAGE_PATH=$EXPORT_DIR/$PACKAGE_NAME" >> $GITHUB_ENV
92
-
93
- - name: Create GitHub Release
94
- if: env.should_build == 'true'
95
- id: create_release
96
- uses: softprops/action-gh-release@v2
97
- with:
98
- tag_name: v${{ env.NEW_VERSION }}
99
- release_name: "Unity Helpers v${{ env.NEW_VERSION }}"
100
- body: "Automatically generated release for version ${{ env.NEW_VERSION }}."
101
- draft: false
102
- prerelease: ${{ env.IS_PRERELEASE == 'true' }}
103
- files: ${{ env.PACKAGE_PATH }}
104
- env:
105
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}