How to check if IAspect has an optional component?

Hello!

I am trying to get started with Unity ECS and run into difficulties checking if an IAspect has an optional component. As far as I can tell I am supposed to use “_myOptionalComponent.IsValid” within the aspect struct to check if the component exists, however, even if I am fairly sure that the component should exist .IsValid always returns “False”.

Consider this simple system:

Components:

using Unity.Entities;

namespace Test
{
    public struct TestValueComponent : IComponentData
    {
        public int ValueWithTag;
        public int ValueWithoutTag;
    }

    public struct TestTag : IComponentData { }
}

Authoring + Baking:

using Unity.Entities;
using UnityEngine;

namespace Test
{
    public class TestAuthoring : MonoBehaviour
    {
        public bool AddTestTag;
    }

    public class TestBaker : Baker<TestAuthoring>
    {
        public override void Bake(TestAuthoring authoring)
        {
            if (authoring.AddTestTag)
            {
                AddComponent<TestTag>();
            }

            AddComponent(new TestValueComponent
            {
                ValueWithTag = 0,
                ValueWithoutTag= 1
            });
        }
    }
}
}

Aspect:

using Unity.Entities;

namespace Test
{
    public readonly partial struct TestAspect : IAspect
    {
        private readonly RefRO<TestValueComponent> _testComponent;

// I think the problem is somewhere around here?
        [Optional] private readonly RefRO<TestTag> _testTag;
        public bool HasTag() => _testTag.IsValid;

        public int GetValueWithTag() => _testComponent.ValueRO.ValueWithTag;

        public int GetValueWithoutTag() => _testComponent.ValueRO.ValueWithoutTag;
    }
}

System + Job:

using Unity.Burst;
using Unity.Entities;

namespace Test
{
    [BurstCompile]
    public partial struct TestSystem : ISystem
    {
        [BurstCompile]
        public void OnCreate(ref SystemState state) { }

        [BurstCompile]
        public void OnDestroy(ref SystemState state) { }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            new TestJob
            {
            }.ScheduleParallel();
        }
    }

    [BurstCompile]
    public partial struct TestJob : IJobEntity
    {
        [BurstCompile]
        private void Execute(ref TestAspect aspect)
        {
            if (aspect.HasTag())
            {
                UnityEngine.Debug.Log(aspect.GetValueWithTag().ToString());
            }
            else
            {
                UnityEngine.Debug.Log(aspect.GetValueWithoutTag().ToString());
            }
        }
    }
}

Then I create a new GameObject within an empty subscene and add the TestAuthoring script. Now, from what I understand, the moment I enter player I should get a lot of "0"s in the console when I have checked the “AddTestTag” checkbox on the TestAuthoring Gameobject and “1” if I didnt. However, in both cases, I only get "1"s, i.e. the aspect doesnt find the optional component even if the Inspector tells me that it is attached to the entity.

I am fairly sure that I am overlooking something really obvious here, but as it stands I am at my wit’s end. Thanks in advance for your help!

Just from your code I don’t see anything obvious.
Couples of questions :
Is your authoring component bool set to true in the editor ?
Have you tried to do the same thing with a non tag component?

1 Like

Thanks, you found the problem!

It works when I change

public struct TestTag : IComponentData { }

to

public struct TestTag : IComponentData
    {
        public float ValueThatWillNeverBeUsed;
    }

So, I suppose optional tag components aren’t supported?

5 Likes

I’m just going to bump this, since I’ve just ran into this unexpected behaviour myself and I believe it should either be fixed or at least documented.

1 Like

I have a same problem. IsValid doesn’t work for TagComponent in Aspect. I added a fake value in my component to avoid the problem.

Thanks for the thread, I was able to understand my problem more quickly.

If there is no value maybe you should consider enabled component as an alternative.