|
// Spawns a game object and link it to the entity this component is attached to. |
|
// The linked game object will have the local transform of the entity copied to its transform automatically by the system |
|
// Any additional monobehaviour can be made accessible from the ECS world by implementing the ICompanionComponent interface |
|
// |
|
// Note: Game Object / Entity destruction is not handled in this gist |
|
public class CompanionObjectAuthoring : MonoBehaviour { |
|
[SerializeField] GameObject prefab; |
|
|
|
class Baker : Baker<CompanionObjectAuthoring> { |
|
public override void Bake(CompanionObjectAuthoring authoring) { |
|
Entity e = GetEntity(TransformUsageFlags.Dynamic); |
|
AddComponent(e, new CompanionObjectPrefab { |
|
reference = authoring.prefab, |
|
}); |
|
} |
|
} |
|
} |
|
|
|
public struct CompanionObject : IComponentData { |
|
public UnityObjectRef<GameObject> reference; |
|
public GameObject GameObject => reference.Value; |
|
} |
|
|
|
public struct CompanionObjectPrefab : IComponentData { |
|
public UnityObjectRef<GameObject> reference; |
|
public GameObject Prefab => reference.Value; |
|
} |
|
|
|
public interface ICompanionComponent { |
|
void CreateCompanionComponent(EntityCommandBuffer ecb, Entity entity); |
|
} |
|
|
|
public partial class CompanionObjectSystemGroup : ComponentSystemGroup {} |
|
|
|
[UpdateInGroup(typeof(CompanionObjectInitializeSystemGroup))] |
|
public partial struct InstantiateCompanionObjectSystem : ISystem { |
|
public void OnUpdate(ref SystemState state) { |
|
EntityCommandBuffer ecb = new(state.WorldUpdateAllocator); |
|
|
|
foreach ((CompanionObjectPrefab companionObjectPrefab, Entity e) |
|
in SystemAPI.Query<CompanionObjectPrefab>().WithNone<CompanionObject>().WithEntityAccess()) { |
|
InstantiateCompanionObject(companionObjectPrefab.Prefab, ecb, e); |
|
} |
|
|
|
ecb.Playback(state.EntityManager); |
|
} |
|
|
|
static void InstantiateCompanionObject(GameObject prefab, EntityCommandBuffer ecb, Entity e) { |
|
GameObject companion = Object.Instantiate(prefab); |
|
ecb.AddComponent(e, new CompanionObject { reference = companion }); |
|
|
|
foreach (ICompanionComponent companionComponent in companion.GetComponents<ICompanionComponent>()) { |
|
companionComponent.CreateCompanionComponent(ecb, e); |
|
} |
|
} |
|
} |
|
|
|
public partial class SyncTransformSystem : SystemBase { |
|
protected override void OnUpdate() { |
|
foreach ((RefRO<LocalTransform> localTransform, CompanionObject companionObject) |
|
in SystemAPI.Query<RefRO<LocalTransform>, CompanionObject>()) { |
|
SyncTransform(companionObject.GameObject, localTransform.ValueRO); |
|
} |
|
} |
|
|
|
void SyncTransform(GameObject companionObject, in LocalTransform localTransform) { |
|
companionObject.transform.position = localTransform.Position; |
|
companionObject.transform.rotation = localTransform.Rotation; |
|
companionObject.transform.localScale = Vector3.one * localTransform.Scale; |
|
} |
|
} |