Search Unity

Why can't we reference TextMeshProUGUI inside IComponentData?

Discussion in 'Entity Component System' started by alexandre-fiset, Feb 18, 2020.

  1. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    At the moment it is unfortunately impossible to reference TextMeshProUGUI inside an IComponentData class.

    At build time it throws this error:

    Code (CSharp):
    1. Something went wrong while Post Processing the assembly (Main.dll) :
    2. Member 'UnityEngine.TextCore.Glyph' is declared in another module and needs to be imported
    3.   at Mono.Cecil.MetadataBuilder.LookupToken (Mono.Cecil.IMetadataTokenProvider provider) [0x0003c] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    4.   at Mono.Cecil.SignatureWriter.MakeTypeDefOrRefCodedRID (Mono.Cecil.TypeReference type) [0x00000] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    5.   at Mono.Cecil.SignatureWriter.WriteTypeSignature (Mono.Cecil.TypeReference type) [0x00161] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    6.   at Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature (Mono.Cecil.IGenericInstance instance) [0x00021] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    7.   at Mono.Cecil.SignatureWriter.WriteTypeSignature (Mono.Cecil.TypeReference type) [0x000cf] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    8.   at Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature (Mono.Cecil.IGenericInstance instance) [0x00021] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    9.   at Mono.Cecil.MetadataBuilder.GetMethodSpecSignature (Mono.Cecil.MethodSpecification method_spec) [0x00023] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    10.   at Mono.Cecil.MetadataBuilder.CreateMethodSpecRow (Mono.Cecil.MethodSpecification method_spec) [0x00012] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    11.   at Mono.Cecil.MetadataBuilder.GetMethodSpecToken (Mono.Cecil.MethodSpecification method_spec) [0x00000] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    12.   at Mono.Cecil.MetadataBuilder.LookupToken (Mono.Cecil.IMetadataTokenProvider provider) [0x000cb] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    13.   at Mono.Cecil.Cil.CodeWriter.WriteOperand (Mono.Cecil.Cil.Instruction instruction) [0x00229] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    14.   at Mono.Cecil.Cil.CodeWriter.WriteInstructions () [0x0002c] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    15.   at Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody (Mono.Cecil.MethodDefinition method) [0x0002e] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    16.   at Mono.Cecil.Cil.CodeWriter.WriteMethodBody (Mono.Cecil.MethodDefinition method) [0x0002b] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    17.   at Mono.Cecil.MetadataBuilder.AddMethod (Mono.Cecil.MethodDefinition method) [0x00013] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    18.   at Mono.Cecil.MetadataBuilder.AddMethods (Mono.Cecil.TypeDefinition type) [0x00013] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    19.   at Mono.Cecil.MetadataBuilder.AddType (Mono.Cecil.TypeDefinition type) [0x000a2] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    20.   at Mono.Cecil.MetadataBuilder.AddTypes () [0x00018] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    21.   at Mono.Cecil.MetadataBuilder.BuildTypes () [0x00014] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    22.   at Mono.Cecil.MetadataBuilder.BuildModule () [0x0009f] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    23.   at Mono.Cecil.MetadataBuilder.BuildMetadata () [0x00000] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    24.   at Mono.Cecil.ModuleWriter+<>c.<BuildMetadata>b__2_0 (Mono.Cecil.MetadataBuilder builder, Mono.Cecil.MetadataReader _) [0x00000] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    25.   at Mono.Cecil.ModuleDefinition.Read[TItem,TRet] (TItem item, System.Func`3[T1,T2,TResult] read) [0x00025] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    26.   at Mono.Cecil.ModuleWriter.BuildMetadata (Mono.Cecil.ModuleDefinition module, Mono.Cecil.MetadataBuilder metadata) [0x0000f] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    27.   at Mono.Cecil.ModuleWriter.Write (Mono.Cecil.ModuleDefinition module, Mono.Disposable`1[T] stream, Mono.Cecil.WriterParameters parameters) [0x000fb] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    28.   at Mono.Cecil.ModuleWriter.WriteModule (Mono.Cecil.ModuleDefinition module, Mono.Disposable`1[T] stream, Mono.Cecil.WriterParameters parameters) [0x00002] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    29.   at Mono.Cecil.ModuleDefinition.Write (System.IO.Stream stream, Mono.Cecil.WriterParameters parameters) [0x00019] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    30.   at Mono.Cecil.AssemblyDefinition.Write (System.IO.Stream stream, Mono.Cecil.WriterParameters parameters) [0x00000] in <58b86858c52b4b5fbb6efedd16c9c16a>:0
    31.   at Unity.Entities.CodeGen.EntitiesILPostProcessors.Process (Unity.CompilationPipeline.Common.ILPostProcessing.ICompiledAssembly compiledAssembly) [0x000df] in C:\Plastic\2019_kona2\Library\PackageCache\com.unity.entities@0.6.0-preview.24\Unity.Entities.CodeGen\EntitiesILPostProcessor.cs:58
    32.   at UnityEditor.Scripting.ScriptCompilation.ILPostProcessing.RunILPostProcessors (UnityEditor.Scripting.ScriptCompilation.ScriptAssembly assembly, System.String outputTempPath) [0x0011b] in <c10752821eec4acbb89ccd53fbbc5e27>:0
    33.   at UnityEditor.Scripting.ScriptCompilation.ILPostProcessing.PostProcess (UnityEditor.Scripting.ScriptCompilation.ScriptAssembly assembly, System.Collections.Generic.List`1[T] messages, System.String outputTempPath) [0x00061] in <c10752821eec4acbb89ccd53fbbc5e27>:0
    34.  

    Is there any reason for this?

    The workaround is to store it in a Monobehaviour and add it on an entity through AddComponentObject. This is not very convenient.
     
  2. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    IComponentData cannot contain any managed references. The MonoBehaviour/AddComponentObject workaround you describe is the only way to do it for the time being.
     
  3. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    That is not true, a IComponentData class can hold managed references.
     
  4. l33t_P4j33t

    l33t_P4j33t

    Joined:
    Jul 29, 2019
    Posts:
    232
    i think thats only while running on the main thread and without burst.. no?
     
  5. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    Of course, anything "Ui" at the moment can't run anywhere else anyway.
     
  6. Curlyone

    Curlyone

    Joined:
    Mar 15, 2018
    Posts:
    41
    i have the same problem, were you able to fix this ? or you stick with AddComponentObject way ?
     
  7. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    What I do for UI is that I have one IComponentData struct that is just a tag, and a ComponentObject that is a Monobehaviour referencing every MonoBehaviour or ScriptableObject that I need in a specific context.

    This way all ECS systems requiring just some data can do it in burst and jobs, but UI-specific things are running in non-burst on the main thread.

    The advantage of this is as some components become available in ECS, I just have to move them to the struct until all are gone.

    Ex:

    Code (CSharp):
    1. using TMPro;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. namespace Ui.Views.ItemInspector
    5. {
    6.      public class ItemInspectorViewObject : MonoBehaviour
    7.      {
    8.          public TextMeshProUGUI TitleText = null;
    9.          public TextMeshProUGUI DescriptionText = null;
    10.          public Image SpriteImage = null;
    11.    
    12.      }
    13. }
    Code (CSharp):
    1. using Items.EquippedAnimation.InspectMode;
    2. using Parabole.Ui.ViewSystem;
    3. using Ui.ScriptableObjects;
    4. using Unity.Entities;
    5.  
    6. namespace Ui.Views.ItemInspector
    7. {
    8.     [UpdateInGroup(typeof(InspectModeSystemGroup))]
    9.     [UpdateAfter(typeof(TriggerInspectModeEquipSystem))]
    10.     public class ItemInspectorViewShowSystem : SystemBase
    11.     {
    12.         private EntityQuery _viewQuery;
    13.        
    14.         protected override void OnCreate()
    15.         {
    16.             _viewQuery = GetEntityQuery(
    17.                 ComponentType.ReadOnly<ItemInspectorView>(),
    18.                 ComponentType.ReadOnly<ItemInspectorViewObject>(),
    19.                 ComponentType.ReadOnly<ShowItemInspectorView>(),
    20.                 ComponentType.Exclude<Visible>());
    21.  
    22.             RequireForUpdate(_viewQuery);
    23.         }
    24.  
    25.         protected override void OnUpdate()
    26.         {
    27.             Entities
    28.                 .WithAll<ItemInspectorView>()
    29.                 .WithoutBurst()
    30.                 .ForEach((ItemInspectorViewObject viewObj, in ShowItemInspectorView showItem) =>{
    31.                     var uiData = EntityManager.GetComponentObject<ItemUiData>(showItem.ItemEntity);
    32.                     viewObj.TitleText.SetText(uiData.Name);
    33.                     viewObj.DescriptionText.SetText(uiData.Description);
    34.                     viewObj.SpriteImage.sprite = uiData.Sprites.Sprite_64;})
    35.                 .Run();
    36.  
    37.             EntityManager.AddComponent<Show>(_viewQuery);
    38.         }
    39.     }
    40. }
     
    Curlyone and thebanjomatic like this.