Hi
I’m trying to understand the best way to communicate transforms to a GameObject in my main Scene from my Entity. This is my current setup.
I have a GameObject in a Subscene that is converted to an Entity with the the following Authoring script to tag it.
public struct FollowTag : IComponentData { }
[DisallowMultipleComponent]
public class FollowTagAuthoring : MonoBehaviour
{
class Baker : Baker<FollowTagAuthoring>
{
public override void Bake(FollowTagAuthoring authoring)
{
Entity entity = GetEntity(TransformUsageFlags.None);
AddComponent(entity, new FollowTag {});
}
}
}
I then have a GameObject in my MainScene which I want to follow the Entity, with the following MonoBehaviour.
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
public class EntityFollow : MonoBehaviour
{
private EntityManager entityManager;
private Entity targetEntity;
private void Start()
{
entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
}
private void Update()
{
if (entityManager != null) {
if (entityManager.Exists(targetEntity))
{
var entityTransform = entityManager.GetComponentData<LocalToWorld>(targetEntity);
var deltaTime = Time.deltaTime;
var smoothTime = 8.0f;
float t = 1 - Mathf.Exp(-smoothTime * deltaTime);
transform.position = math.lerp(transform.position, entityTransform.Position, t);
} else {
FindTaggedEntity();
}
}
}
private void FindTaggedEntity()
{
// Find the entity with the FollowTag
entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
EntityQuery query = entityManager.CreateEntityQuery(typeof(FollowTag), typeof(LocalToWorld));
if (!query.IsEmpty) {
var entities = query.ToEntityArray(Allocator.TempJob);
if (entities.Length > 0)
{
targetEntity = entities[0]; // only follow first
Debug.Log("following entity: " + targetEntity.Index);
}
entities.Dispose();
} else {
Debug.Log("no entity found to follow yet.");
}
}
}
This works, however I initially just had the Start() method call FindTaggedEntity() but this only worked in the Editor Player. When I created a build and ran it, I realized of course that the Entity did not exist yet when the MonoBehaviour Start() method is executed. I adapted my script to what is above, which works OK, however I see in the Player.log that it takes about 13 frames before the entity is “found”.
I would much rather get some direction on how to do this properly for when it gets detrimental to performance to blindly keep querying until an entity is found. (besides some rudimentary delay/polling methods)
I’ve seen some solutions in the forum, but nothing that made exactly sense for my use case. (I’m very new to ECS, so excuse the question if it is completely basic.)
A side question - I know the Editor Player is quite different than a build, but in this specific case, is it because the Editor already has the Entity created that a EntityQuery in the MonoBehaviour’s Start() method would pick it up?
Any feedback or direction would be very much appreciated.