Does the Parent component get removed from Entity if its Value is not set?

Practicing some ECS and tried to make a system where an object is set as the child of an entity it collides with. Until then it flies through the air without a Parent component. Think an arrow flying through the air but becoming a child of an Enemy entity so that it appears stuck on them.

So I thought I’d just add the Parent component to the arrow in my component authoring script, but not set Value to anything. But then it happened, the entity that I added the Parent component before didn’t have it anymore on time of collision. I am sure that I do not have any remove component calls anywhere, so unless there is some weird DOTS gotcha that certain unset components are removed then I wouldn’t know what’s up. So I tried setting the Parent component to different values:

  • struct default
  • Entity.Null
  • itself
  • some manager entity (essentially was thinking of having a manager of sorts to keep count and pool these entities so thought I’d just set the Parent to that.

The first 3 had the same problem of the Parent component disappearing. The last worked, but messed with the physics of the entity so it was not clean solution.

So yeah, is there something I may be missing here? I ended up learning about EntityCommandBuffers to add a Parent component on collision within a job, but I’m still confused as to why my previous approach didn’t work.

You may want to read the MANUAL to understand how these things work in ECS now.

In short - No, there is no such system that removes invalid Parent components - at least in Entities 0.13.0.

But to inspect that yourself, go to ...\Projec_Name\Library\PackageCache\com.unity.entities@0.13.0-preview.24\Unity.Transforms directory, look for files ending with ...System and read their source code yourself.

For a reference, this is how you can setup a working parent-child transform relationship:

using UnityEngine;
using Random = UnityEngine.Random;
  
using Unity.Mathematics;
using Unity.Entities;
using Unity.Transforms;
  
public class Test : MonoBehaviour
{
  
	World world = default(World);
	EntityManager command = default(EntityManager);
  
	Entity PARENT = Entity.Null;
	Entity CHILD = Entity.Null;
  
	void Start ()
	{
		world = World.DefaultGameObjectInjectionWorld;
		command = world.EntityManager;
		
		// CREATE PARENT ENTITY:
		PARENT = command.CreateEntity(
			typeof(LocalToWorld) ,
			typeof(Translation) ,
			typeof(Rotation) ,
			typeof(Scale)
		);
		command.SetName( PARENT , "parent" );
		command.SetComponentData( PARENT , new LocalToWorld{
			Value = float4x4.identity
		} );
		command.SetComponentData( PARENT , new Translation{
			Value = Random.onUnitSphere
		} );
		command.SetComponentData( PARENT , new Rotation{
			Value = Random.rotation
		} );
		command.SetComponentData( PARENT , new Scale{
			Value = 1f
		} );
  
		// CREATE CHILD ENTITY:
		CHILD = command.CreateEntity(
			typeof(LocalToWorld) ,
			typeof(LocalToParent) ,
			typeof(Parent)
		);
		command.SetName( CHILD , "child" );
		command.SetComponentData( CHILD , new LocalToWorld{
			Value = float4x4.identity
		} );
		command.SetComponentData( CHILD , new LocalToParent{
			Value = float4x4.TRS( Random.onUnitSphere , Random.rotation , Random.onUnitSphere )
		} );
		command.SetComponentData( CHILD , new Parent{
			Value = PARENT
		} );
	}
  
	void Update ()
	{
		var LTW = command.GetComponentData<LocalToWorld>( PARENT );
		{
			float t = (float) math.sin( UnityEditor.EditorApplication.timeSinceStartup );
			LTW.Value = math.mul( LTW.Value , float4x4.Translate( new float3{ x=t , y=t , z=t } ) );
		}
		command.SetComponentData( PARENT , LTW );
	}
  
}