GetPrimaryEntity in a GameObjectConversionSystem return non-existant entity

I’ve been using GameObjectConversionSystem to convert gameobjects to entities, and I’ve encountered a weird issue.

I used to use the GetPrimaryEntity method on my authoring component (which has a ConvertToEntity script on its game object), but for some reasons it won’t work in a system that I created this morning.

This:

using Ui.Components;
using Ui.Components.States;
using Ui.Screens.Authoring;
using Unity.Entities;

namespace Ui.Screens.Systems
{
    [UpdateInGroup(typeof(GameObjectConversionGroup))]
    public class DpadInventoryConversionSystem : GameObjectConversionSystem
    {
        protected override void OnUpdate()
        {
            Entities.ForEach((DpadInventoryAuthoring authoring) =>
            {
                var entity = GetPrimaryEntity(authoring);
                EntityManager.AddComponentData(entity, new Hidden());

                var dInventory = new DpadInventory
                {
                    SelectedSlotColor = authoring.SelectedSlotColor,
                    UnselectedColor = authoring.UnselectedColor,
                    Slots = authoring.Slots,
                    TopText = authoring.TopText,
                    MiddleText = authoring.MiddleText,
                    BottomText = authoring.BottomText
                };
           
                EntityManager.AddSharedComponentData(entity, dInventory);
           
                #if UNITY_EDITOR
                EntityManager.SetName(entity, "Ui.DpadInventory");
                #endif
            });
  
        }

    }
}

Returns “ArgumentException: The entity does not exist” on the first AddComponentData line.

Any idea why is that?

You’re using wrong world.

You need to use dstEntityManager

3 Likes

That is a bit confusing, but it works :stuck_out_tongue: Thanks!

You have to understand how conversion works.

The first step is to create entities for all go and attach all monobehaviour to them in a new temp conversion world.

Then it creates new empty entities in the destination world for these entities.

The conversion world is what you are iterating with entities.Foreach but when you call get primary entity you are getting the entity from the destination world so that you can add components to it.

6 Likes

Is there another transfer form dstWord to default world or is the dtsWorld the default world

dstWorld is whatever world you pass to the GameObjectConversionSettings when you create a conversion world. For default conversion, like scene conversion, this is going to be World.Active.
So no, there is copy.

Thanks for the clarification, one more question, does CreateAdditionalEntity add the entity to the dstWorld

1 Like

Yes it’s created on the destination world.

This is something you can find out yourself looking at source code for 30 seconds.

public Entity CreateAdditionalEntity(GameObject go)
    {
        #if DETAIL_MARKERS
        using (m_CreateAdditional.Auto())
        #endif
        {
            if (go == null)
                throw new ArgumentException("CreateAdditionalEntity must be called with a valid GameObject");

            var instanceID = go.GetInstanceID();
            int index;
            if (m_GameObjectToEntity.TryGetValue(instanceID, out index))
            {
                int count = m_Entities.CountLinkedList(index);
                var entity = CreateEntity(go, count);

CreateAdditionalEntity calls CreateEntity (if it doesn’t exist)

 Entity CreateEntity(UnityObject uobject, int index)
    {
        #if DETAIL_MARKERS
        using (m_CreateEntity.Auto())
        #endif
        {
            int flags = 0;
            if (AddEntityGUID)
                flags |= k_EntityGUIDMask;

            var go = uobject as GameObject;
            if (go != null)
            {
                if (ForceStaticOptimization || go.GetComponentInParent<StaticOptimizeEntity>() != null)
                    flags |= k_StaticMask;
                if (!IsActive(go))
                    flags |= k_DisabledMask;
            }
            else if (uobject is Component)
                throw new ArgumentException("Object must be a GameObject, Prefab, or Asset", nameof(uobject));

            var entity = m_DstManager.CreateEntity(m_Archetypes[flags]);

CreateEntity uses m_DstManager to create entity

1 Like

Thanks again, sorry didnt have the source code in front of me and jump on the opportunity to ask.

What I really want to understand is how this is all handled with sub scenes. I find it extreme difficult to track where entitles exist especially at run time when I change values on a game object.

The problem you’re having is that you’re trying to do some very strange things with subscenes and conversion that no one else is doing or has done which means unfortunately no one has any experience to provide help . When you’re the first to do something, you kind of have to figure it out yourself.

Yea fair enough