Skip to content

Commit c671142

Browse files
committed
Required only monobehaviours, and root game object game pools
1 parent 2ae26a9 commit c671142

File tree

3 files changed

+185
-20
lines changed

3 files changed

+185
-20
lines changed

packages/com.seaube.ecs-idl/Runtime/EcsIdl.cs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Collections.Generic;
44
using System.Reflection;
5+
using System.Runtime.InteropServices;
56

67
using ComponentIdsList = System.Collections.Generic.SortedSet<System.Int32>;
78

@@ -15,6 +16,11 @@ public interface Component {}
1516
public interface Action {}
1617

1718
public static class Util {
19+
private static Dictionary<Int32, Type> cachedComponentTypes;
20+
21+
static Util() {
22+
cachedComponentTypes = new Dictionary<Int32, Type>();
23+
}
1824

1925
public static bool IsComponent
2026
( System.Type componentType
@@ -29,10 +35,37 @@ public static bool IsComponent
2935
return false;
3036
}
3137

38+
public static object? PtrToComponent
39+
( IntPtr componentIntPtr
40+
, System.Int32 componentId
41+
)
42+
{
43+
var componentType = GetComponentType(componentId);
44+
45+
if(componentType != null) {
46+
return Marshal.PtrToStructure(componentIntPtr, componentType);
47+
}
48+
49+
return null;
50+
}
51+
52+
public static void ComponentToPtr
53+
( object component
54+
, System.Int32 componentId
55+
, IntPtr componentIntPtr
56+
)
57+
{
58+
Marshal.StructureToPtr(component, componentIntPtr, false);
59+
}
60+
3261
public static System.Type? GetComponentType
3362
( System.Int32 componentId
3463
)
3564
{
65+
if(cachedComponentTypes.TryGetValue(componentId, out var t)) {
66+
return t;
67+
}
68+
3669
foreach(var assembly in System.AppDomain.CurrentDomain.GetAssemblies()) {
3770
foreach(var type in assembly.GetTypes()) {
3871
if(IsComponent(type)) {
@@ -47,6 +80,10 @@ public static System.Type? GetComponentType
4780
return null;
4881
}
4982

83+
public static void ClearComponentTypeCache() {
84+
cachedComponentTypes.Clear();
85+
}
86+
5087
public static System.Int32 GetComponentID<T>() where T : EcsIdl.Component {
5188
return GetComponentID(typeof(T));
5289
}
@@ -55,12 +92,18 @@ public static System.Int32 GetComponentID
5592
( System.Type componentType
5693
)
5794
{
95+
if(!IsComponent(componentType)) {
96+
throw new ArgumentException("Invalid component type");
97+
}
98+
5899
var idField = componentType.GetField(
59100
"id",
60101
BindingFlags.Static | BindingFlags.Public
61102
);
62103

63-
return (System.Int32)idField.GetValue(null);
104+
var componentId = (System.Int32)idField.GetValue(null);
105+
cachedComponentTypes[componentId] = componentType;
106+
return componentId;
64107
}
65108

66109
public static System.Int32 GetActionID<T>() where T : EcsIdl.Action {

packages/com.seaube.ecs-idl/Runtime/EcsIdlUnitySync.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ namespace EcsIdl.UnitySync {
2525
/// behaviour is added.</summary>
2626
public interface IRequired<T> where T : EcsIdl.Component {}
2727

28+
public interface IOnInitEntity {
29+
void OnInitEntity(System.Int32 entityId);
30+
}
31+
2832
public interface IOnInitComponent<T> where T : EcsIdl.Component {
2933
void OnInitComponent(in T component);
3034
}
@@ -208,7 +212,30 @@ public static IEnumerable<Type> GetTypes
208212
var usedTypes = new HashSet<Type>();
209213

210214
foreach(var compId in compIds) {
211-
if(onInitBehavioursMap.TryGetValue(compId, out var types)) {
215+
if(requiredBehavioursMap.TryGetValue(compId, out var types)) {
216+
foreach(var type in types) {
217+
if(usedTypes.Contains(type)) continue;
218+
219+
if(requiredComponentsMap.TryGetValue(type, out var reqCompIds)) {
220+
bool missingRequired = false;
221+
foreach(var reqCompId in reqCompIds) {
222+
if(!compIds.Contains(reqCompId)) {
223+
missingRequired = true;
224+
break;
225+
}
226+
}
227+
228+
if(missingRequired) {
229+
continue;
230+
}
231+
}
232+
233+
yield return type;
234+
usedTypes.Add(type);
235+
}
236+
}
237+
238+
if(onInitBehavioursMap.TryGetValue(compId, out types)) {
212239
foreach(var type in types) {
213240
if(usedTypes.Contains(type)) continue;
214241

packages/com.seaube.ecs-idl/Runtime/EntityGameObjectPool.cs

Lines changed: 113 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,46 @@ public static EntityGameObjectPool CreateInstance() {
2626
public Scene? targetScene {
2727
get => _targetScene;
2828
set {
29+
if(_rootGameObject != null) {
30+
throw new System.ArgumentException(
31+
"EntityGameObjectPool.targetScene may not be set if " +
32+
"EntityGameObjectPool.rootGameObject is set."
33+
);
34+
}
35+
36+
if(_targetScene != null && value != null) {
37+
if(_targetScene.Equals(value)) {
38+
return;
39+
}
40+
}
41+
2942
_targetScene = value;
3043
MoveEntityGameObjectsIfNeeded();
3144
}
3245
}
3346

47+
private GameObject? _rootGameObject;
48+
public GameObject? rootGameObject {
49+
get => _rootGameObject;
50+
set {
51+
if(_targetScene != null) {
52+
throw new System.ArgumentException(
53+
"EntityGameObjectPool.rootGameObject may not be set if " +
54+
"EntityGameObjectPool.targetScene is set."
55+
);
56+
}
57+
58+
if(_rootGameObject != null && value != null) {
59+
if(GameObject.ReferenceEquals(_rootGameObject, value)) {
60+
return;
61+
}
62+
}
63+
64+
_rootGameObject = value;
65+
ReparentEntityGameObjects();
66+
}
67+
}
68+
3469
private EntityGameObjectPool() {
3570
entityComponentIds = new List<ComponentIdsList>();
3671
entityGameObjects = new List<GameObject?>();
@@ -101,8 +136,9 @@ public void InitComponent
101136
currentComponentIds: compIds
102137
);
103138

139+
GameObject? gameObject = null;
104140
if(removedTypes.Any() && entityGameObjects[entityId] != null) {
105-
var gameObject = entityGameObjects[entityId]!;
141+
gameObject = entityGameObjects[entityId]!;
106142
foreach(var type in removedTypes) {
107143
if(gameObject.TryGetComponent(type, out var removedComponent)) {
108144
UnityEngine.Object.Destroy(removedComponent);
@@ -111,38 +147,78 @@ public void InitComponent
111147
}
112148

113149
if(addedTypes.Any()) {
114-
var gameObject = EnsureEntityGameObject(entityId);
150+
gameObject = EnsureEntityGameObject(entityId);
115151
gameObject.SetActive(true);
116152
foreach(var type in addedTypes) {
117-
UnitySyncMonoBehaviours.InvokeOnInit(
118-
(MonoBehaviour)gameObject.AddComponent(type),
119-
componentId,
120-
in component
121-
);
153+
var newMonoBehaviour = (MonoBehaviour)gameObject.AddComponent(type);
154+
IOnInitEntity? onInitEntity = newMonoBehaviour as IOnInitEntity;
155+
if(onInitEntity != null) {
156+
onInitEntity.OnInitEntity(entityId);
157+
}
122158
}
123159
}
160+
161+
gameObject = gameObject ?? GetEntityGameObject(entityId);
162+
163+
if(gameObject != null) {
164+
UnitySyncMonoBehaviours.InvokeOnInit(
165+
gameObject,
166+
componentId,
167+
in component
168+
);
169+
}
170+
}
171+
172+
public void UpdateComponent<T>
173+
( System.Int32 entityId
174+
, in T component
175+
) where T : EcsIdl.Component
176+
{
177+
UpdateComponent(
178+
entityId,
179+
EcsIdl.Util.GetComponentID(typeof(T)),
180+
component
181+
);
124182
}
125183

126184
public void UpdateComponent
127185
( System.Int32 entityId
128186
, System.Int32 componentId
129-
, object component
187+
, in object component
130188
)
131189
{
132-
var gameObject = entityGameObjects[entityId];
133-
if(gameObject != null) {
134-
UnitySyncMonoBehaviours.InvokeOnUpdate(
135-
gameObject,
136-
componentId,
137-
component
190+
var gameObject = GetEntityGameObject(entityId);
191+
if(gameObject == null) {
192+
throw new System.ArgumentException(
193+
$"EntityGameObjectPool.UpdateComponent called before " +
194+
$"EntityGameObjectPool.InitComponent. entityId={entityId}"
138195
);
139196
}
197+
198+
UnitySyncMonoBehaviours.InvokeOnUpdate(
199+
gameObject,
200+
componentId,
201+
in component
202+
);
203+
}
204+
205+
public void RemoveComponent<T>
206+
( System.Int32 entityId
207+
, in T component
208+
) where T : EcsIdl.Component
209+
{
210+
var compObj = (object)component;
211+
RemoveComponent(
212+
entityId,
213+
EcsIdl.Util.GetComponentID(typeof(T)),
214+
in compObj
215+
);
140216
}
141217

142218
public void RemoveComponent
143219
( System.Int32 entityId
144220
, System.Int32 componentId
145-
, object component
221+
, in object component
146222
)
147223
{
148224
if(entityGameObjects[entityId] != null) {
@@ -164,7 +240,7 @@ public void RemoveComponent
164240
UnitySyncMonoBehaviours.InvokeOnRemove(
165241
gameObject,
166242
componentId,
167-
component
243+
in component
168244
);
169245

170246
foreach(var type in removedTypes) {
@@ -178,8 +254,13 @@ public void RemoveComponent
178254
}
179255

180256
foreach(var type in addedTypes) {
257+
var newMonoBehaviour = (MonoBehaviour)gameObject.AddComponent(type);
258+
IOnInitEntity? onInitEntity = newMonoBehaviour as IOnInitEntity;
259+
if(onInitEntity != null) {
260+
onInitEntity.OnInitEntity(entityId);
261+
}
181262
UnitySyncMonoBehaviours.InvokeOnInit(
182-
(MonoBehaviour)gameObject.AddComponent(type),
263+
newMonoBehaviour,
183264
componentId,
184265
in component
185266
);
@@ -206,6 +287,8 @@ private GameObject EnsureEntityGameObject
206287
gameObject = new GameObject($"entity ({entityId})");
207288
if(_targetScene != null && !gameObject.scene.Equals(_targetScene)) {
208289
SceneManager.MoveGameObjectToScene(gameObject, _targetScene.Value);
290+
} else if(_rootGameObject != null) {
291+
gameObject.transform.SetParent(_rootGameObject.transform);
209292
}
210293
entityGameObjects[entityId] = gameObject;
211294
}
@@ -230,6 +313,18 @@ private void EnsureEntityLists
230313
}
231314
}
232315

316+
private void ReparentEntityGameObjects() {
317+
foreach(var gameObject in entityGameObjects) {
318+
if(gameObject != null) {
319+
if(_rootGameObject == null) {
320+
gameObject.transform.SetParent(null);
321+
} else {
322+
gameObject.transform.SetParent(_rootGameObject.transform);
323+
}
324+
}
325+
}
326+
}
327+
233328
private void MoveEntityGameObjectsIfNeeded() {
234329
Scene scene = _targetScene == null
235330
? SceneManager.GetActiveScene()
@@ -258,7 +353,7 @@ private void OnChangedActiveScene
258353
, Scene next
259354
)
260355
{
261-
if(_targetScene == null) {
356+
if(_targetScene == null && _rootGameObject == null) {
262357
MoveEntityGameObjectsIfNeeded();
263358
}
264359
}

0 commit comments

Comments
 (0)