Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question How to check if IAspect has an optional component?

Discussion in 'Entity Component System' started by WeekendWarrior, Jan 22, 2023.

  1. WeekendWarrior

    WeekendWarrior

    Joined:
    Jan 6, 2016
    Posts:
    6
    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:

    Code (CSharp):
    1.  
    2. using Unity.Entities;
    3.  
    4. namespace Test
    5. {
    6.     public struct TestValueComponent : IComponentData
    7.     {
    8.         public int ValueWithTag;
    9.         public int ValueWithoutTag;
    10.     }
    11.  
    12.     public struct TestTag : IComponentData { }
    13. }
    14.  
    Authoring + Baking:

    Code (CSharp):
    1.  
    2. using Unity.Entities;
    3. using UnityEngine;
    4.  
    5. namespace Test
    6. {
    7.     public class TestAuthoring : MonoBehaviour
    8.     {
    9.         public bool AddTestTag;
    10.     }
    11.  
    12.     public class TestBaker : Baker<TestAuthoring>
    13.     {
    14.         public override void Bake(TestAuthoring authoring)
    15.         {
    16.             if (authoring.AddTestTag)
    17.             {
    18.                 AddComponent<TestTag>();
    19.             }
    20.  
    21.             AddComponent(new TestValueComponent
    22.             {
    23.                 ValueWithTag = 0,
    24.                 ValueWithoutTag= 1
    25.             });
    26.         }
    27.     }
    28. }
    29. }
    30.  
    Aspect:

    Code (CSharp):
    1.  
    2. using Unity.Entities;
    3.  
    4. namespace Test
    5. {
    6.     public readonly partial struct TestAspect : IAspect
    7.     {
    8.         private readonly RefRO<TestValueComponent> _testComponent;
    9.  
    10. // I think the problem is somewhere around here?
    11.         [Optional] private readonly RefRO<TestTag> _testTag;
    12.         public bool HasTag() => _testTag.IsValid;
    13.  
    14.         public int GetValueWithTag() => _testComponent.ValueRO.ValueWithTag;
    15.  
    16.         public int GetValueWithoutTag() => _testComponent.ValueRO.ValueWithoutTag;
    17.     }
    18. }
    19.  

    System + Job:

    Code (CSharp):
    1.  
    2. using Unity.Burst;
    3. using Unity.Entities;
    4.  
    5. namespace Test
    6. {
    7.     [BurstCompile]
    8.     public partial struct TestSystem : ISystem
    9.     {
    10.         [BurstCompile]
    11.         public void OnCreate(ref SystemState state) { }
    12.  
    13.         [BurstCompile]
    14.         public void OnDestroy(ref SystemState state) { }
    15.  
    16.         [BurstCompile]
    17.         public void OnUpdate(ref SystemState state)
    18.         {
    19.             new TestJob
    20.             {
    21.             }.ScheduleParallel();
    22.         }
    23.     }
    24.  
    25.     [BurstCompile]
    26.     public partial struct TestJob : IJobEntity
    27.     {
    28.         [BurstCompile]
    29.         private void Execute(ref TestAspect aspect)
    30.         {
    31.             if (aspect.HasTag())
    32.             {
    33.                 UnityEngine.Debug.Log(aspect.GetValueWithTag().ToString());
    34.             }
    35.             else
    36.             {
    37.                 UnityEngine.Debug.Log(aspect.GetValueWithoutTag().ToString());
    38.             }
    39.         }
    40.     }
    41. }
    42.  
    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!
     
  2. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    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?
     
    WeekendWarrior likes this.
  3. WeekendWarrior

    WeekendWarrior

    Joined:
    Jan 6, 2016
    Posts:
    6
    Thanks, you found the problem!

    It works when I change

    Code (CSharp):
    1. public struct TestTag : IComponentData { }
    to

    Code (CSharp):
    1. public struct TestTag : IComponentData
    2.     {
    3.         public float ValueThatWillNeverBeUsed;
    4.     }
    So, I suppose optional tag components aren't supported?
     
  4. jhelbig

    jhelbig

    Joined:
    Jul 25, 2019
    Posts:
    6
    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.
     
    NoPants_ likes this.