public void LinkGameObjectToSpatialOSEntity(EntityId entityId, GameObject gameObject, params Type[] componentTypesToAdd) { var linkedComponent = gameObject.GetComponent <LinkedEntityComponent>(); if (linkedComponent == null) { linkedComponent = gameObject.AddComponent <LinkedEntityComponent>(); } else if (linkedComponent.IsValid) { throw new InvalidOperationException( $"GameObject is already linked to the entity with ID {linkedComponent.EntityId}"); } if (!entityIdToGameObjects.TryGetValue(entityId, out var linkedGameObjects)) { linkedGameObjects = new List <GameObject>(); entityIdToGameObjects.Add(entityId, linkedGameObjects); } linkedGameObjects.Add(gameObject); linkedComponent.IsValid = true; linkedComponent.EntityId = entityId; linkedComponent.World = world; linkedComponent.Worker = workerSystem; linkedComponent.Linker = this; var injectors = new List <RequiredSubscriptionsInjector>(); foreach (var component in gameObject.GetComponents <MonoBehaviour>()) { if (component == null) { // todo consider - could also tell the user that they have a bad ref here continue; } var type = component.GetType(); if (RequiredSubscriptionsDatabase.HasRequiredSubscriptions(type) && RequiredSubscriptionsDatabase.WorkerTypeMatchesRequirements(workerSystem.WorkerType, type)) { // todo this should possibly happen when the command buffer is flushed too injectors.Add(new RequiredSubscriptionsInjector(component, entityId, subscriptionSystem, () => lifecycleSystem.EnableMonoBehaviour(component), () => lifecycleSystem.DisableMonoBehaviour(component))); } } gameObjectToInjectors.Add(gameObject, injectors); if (entityId.IsValid()) { AddComponentsToEntity(entityId, gameObject, componentTypesToAdd); } }
// todo should either special case monobehaviours or not use callbacks // for non monobehaviours we could use functors public RequiredSubscriptionsInjector(object target, EntityId entityId, SubscriptionSystem subscriptionSystem, Action onEnable = null, Action onDisable = null) { info = RequiredSubscriptionsDatabase.GetOrCreateRequiredSubscriptionsInfo(target.GetType()); if (info.RequiredTypes.Length == 0) { return; } this.target = target; this.onEnable = onEnable; this.onDisable = onDisable; subscriptions = new SubscriptionAggregate(subscriptionSystem, entityId, info.RequiredTypes); subscriptions.SetAvailabilityHandler(Handler.Pool.Rent(this)); }
// todo should either special case monobehaviours or not use callbacks // for non monobehaviours we could use functors public RequiredSubscriptionsInjector(object target, EntityId entityId, SubscriptionSystem subscriptionSystem, Action onEnable = null, Action onDisable = null) { this.target = target; this.onEnable = onEnable; this.onDisable = onDisable; info = RequiredSubscriptionsDatabase.GetOrCreateRequiredSubscriptionsInfo(target.GetType()); if (info == null || info.RequiredTypes.Length == 0) { onEnable?.Invoke(); return; } subscriptions = subscriptionSystem.Subscribe(entityId, info.RequiredTypes); subscriptions.SetAvailabilityHandler(Handler.Pool.Rent(this)); }