Creating an entity from code, and then communicating with it from Monobehaviours

So first of all, I would like to spawn a GamObject, and then convert it to an entity, through code.

Then, since some pretty important scripts need to communicate with it, and the GameObject itself has one or two scripts on it, I would like the Monobehaviour scripts to be able to call functions (voids) that are in the GameObject (this GameObject would now be an entity) script(s).

I would love any help on this since I am spawning a lot of these GameObjects at once… and by doing that, I’m slowing down the performance.

Here is a most basic example showing how you can communicate with a specific entity from a MonoBehaviour:

  1. Attach PlayerAuthoring & ConvertToEntity components to a capsule shape GameObject & make sure it’s visible to main camera
  2. Attach PlayerController to an empty GameObject
  3. Hit play; capsule shape should move according to your Horizontal/ Vertical axis input.

PlayerAuthoring.cs

using UnityEngine;
using Unity.Entities;
  
namespace Sandbox
{
	public class PlayerAuthoring : MonoBehaviour, IConvertGameObjectToEntity
	{
		[SerializeField] int _index;
		void IConvertGameObjectToEntity.Convert ( Entity e , EntityManager dst , GameObjectConversionSystem cs )
		{
			dst.AddComponentData( e , new Player{
				Index	= _index
			} );
			dst.AddComponent<HumanInput>( e );
		}
	}
}

PlayerController.cs

using UnityEngine;
using Unity.Mathematics;
using Unity.Collections;
using Unity.Entities;
using Unity.Transforms;

namespace Sandbox
{
    public class PlayerController : MonoBehaviour
    {
        [SerializeField] int _index;
        [SerializeField] float _speed = 5f;
        EndSimulationEntityCommandBufferSystem _commandBufferSystem;
        EntityQuery _query;
        void Start ()
        {
            var world = World.DefaultGameObjectInjectionWorld;
            var entityManager = world.EntityManager;
            _commandBufferSystem = world.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
            _query = entityManager.CreateEntityQuery( typeof(Player) , typeof(HumanInput) );
        }
        void Update ()
        {
            int numHumanPlayers = _query.CalculateEntityCount();
            if( numHumanPlayers!=0 )
            {
                var cmd = _commandBufferSystem.CreateCommandBuffer();
                var entityArray = _query.ToEntityArray( Allocator.Temp );
                var playerArray = _query.ToComponentDataArray<Player>( Allocator.Temp );
                for( int i=0 ; i<numHumanPlayers ; i++ )
                {
                    Player player = playerArray;
                    if( player.Index==_index )
                    {
                        Entity entity = entityArray*;
                        cmd.SetComponent( entity , new HumanInput{
                            Horizontal	= Input.GetAxis("Horizontal") * _speed,
                            Vertical	= Input.GetAxis("Vertical") * _speed
                        } );
                    }
                }
            }
        }
    }

    public struct Player : IComponentData
    {
        public int Index;
    }

    public struct HumanInput : IComponentData
    {
        public float Horizontal, Vertical;
    }

    [UpdateInGroup( typeof(SimulationSystemGroup) )]
    public partial class HumanInputSystem : SystemBase
    {
        protected override void OnCreate ()
        {
            base.OnCreate();

            RequireForUpdate( EntityManager.CreateEntityQuery( typeof(HumanInput) ) );
        }
        protected override void OnUpdate ()
        {
            float deltaTime = Time.DeltaTime;
            var camera = Camera.main;
            if( camera==null )
            {
                Debug.LogWarning("main camera not found");
                return;
            }
            var camTransform = camera.transform;
            float3 dirforward = camTransform.forward;
            float3 dirright = camTransform.right;

            Entities
                .WithChangeFilter<HumanInput>()
                .ForEach( ( ref Translation translation , ref Rotation rotation , in HumanInput input ) =>
                {
                    float3 stepforward = new float3(dirforward.x,0,dirforward.z) * input.Vertical;
                    float3 stepright = new float3(dirright.x,0,dirright.z) * input.Horizontal;
                    float3 step = ( stepforward + stepright )*deltaTime;
                    translation.Value += step;

                    if( math.any(step!=0) )
                    {
                        float3 movdir = math.normalize(step);
                        rotation.Value = quaternion.LookRotation( movdir , new float3(0,1,0) );
                    }
                } )
                .WithBurst()
                .ScheduleParallel();
        }
    }
}