- Home /
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 GameObject
s at once... and by doing that, I'm slowing down the performance.
Your descriptions portrays OOP expectations. Entities are DOD territory so change in thinking is advised as well.
What I mean by that is you're not suppose to call functions on entities. Entities represent collection of data (data about player, enemy, tree, cube, collider, whatever). SystemBase
are a place where you write what things happen to that data.
Ah... thanks for replying... but do you know another way of making the performance better, while still being able to communicate with the objects I'm spawning? (they're chunks in a world that I'm wanting to make bigger)
In ecs you communicate with entities by changing their data OR create dedicated entities that pass the message.
Answer by andrew-lukasik · May 31 at 12:06 PM
Here is a most basic example showing how you can communicate with a specific entity from a MonoBehaviour
:
Attach
PlayerAuthoring
&ConvertToEntity
components to a capsule shapeGameObject
& make sure it's visible to main cameraAttach
PlayerController
to an emptyGameObject
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[i];
if( player.Index==_index )
{
Entity entity = entityArray[i];
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();
}
}
}
one problem though, I get an error that says: 'World' does not contain a definition for 'DefaultGameObjectInjectionWorld'
any idea what to do?
Also, make sure you have no custom class named World
as those will name-collide.
Your answer
Follow this Question
Related Questions
Communication between objects and other scripts, variables and properties 1 Answer
How to communicate between scenes??? 2 Answers
Converting some C# pseudo code to UnityScript.... 1 Answer
Cannot see gameobjects in Unity editor (DOTS problem) 0 Answers
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers