SubScenes Help with Live Link

Ok Been trying for past 3 days to get subScenes working , trolled through MegaCity and the HelloCube subscens example but im just not getting this.

Reason I want to used it is for the LiveLink. Can someone please walk me through the process on how to set this up. It seems I need small detailed steps, like a child flip book with pop up animals :frowning:

Thanks in advance.

Create SubScene from current scene:

  • Add a “scene object” and attach all gameobjects that belongs to that scene to it.
  • Select the sceneobject and right click
  • Click on “New SubScene From Selection”

Click “Rebuild Entity Cache” everytime you change something on conversion scripts or prefabs that belongs to the SubScene.

Click close to create entities. All conversion scripts will be excuted for all gameobjects which belongs to the SubScene.

You are done. You should see somthing like this:

3 Likes

Thank you so much, ok seem like my problem was not hitting the “close” button. Collaborate destroyed my project, once im up and running I will test it

Thanks again !!

Ive gotten quite far with sub scenes and live like but Ive run into an unexpected behaviour. Let me explain.

I have a subScene with two game objects for conversion to entities utilizing live link.

4870097--469505--Screen Shot 2019-08-18 at 3.05.04 PM.png

I have two classes implementing GameObjectConversionSystem for each gameObject and one addition class where I want to add addition entites relating to the data from the two entity gameObjects

For GameObject 1


For GameObject 2

and the additional conversion class that add additional entities based on data from the 2 gameobjects.

The main motivation for this is HexSphereBuildConversionSystem is expensive so I wanted to cache the entities in the editor. Live link is needed to get required data from gameObjects (gameObject 1 and gameObject 2).

Seems to work like expected, I press “ReBuild Entity Cache” and I see gameObject 1 and 2 entities and my additional entities from HexSphereBuildConversionSystem.

Now if I run the game it appears that my custom entities are lost.

If enter playmode with the subScenes open by pressing . “Edit” my entities make it all the way through.

Please help me understand what is going on here :frowning:

Here is what my entity debugger looks like in play mode. Missing all my custom entities

Wondering if i need to tag it with some component so it doesn’t get deleted

We have no idea what your code is doing

Basically tying to create and cache entities with no game object using live link. The first two conversions work but it this last one that is not working.

I trying to pay the cost of building these entities in the editor not at run time.

EDIT forgot code

92 entities in the scene ‘Assets/Scripts/HexWorld/HexSphere/HexSphere.Scenes/HexSphereBuildSubScene.unity’ had no SceneSection and as a result were not serialized at all.

using Unity.Collections;
using Unity.Entities;
using System;
using UnityEngine;


namespace Lightbringer.HexWorld
{
    /// <summary>
    /// This class is what builds the entity cache through sub scenes.
    /// It converts hexSphera vertex and triangle data to entity data.
    /// </summary>
    [UpdateAfter(typeof(HexSphereBuildDataConversion))]
    public class HexSphereBuildConversionSystem : GameObjectConversionSystem
    {
        #region FLIELDS --------------------------------------------------------

        private GameObject go;
        private HexSphereBuildDataProxy data;
        internal WORLD_SIZE worldSize;
        private int subdivisionsCount;
        private int raduis;
        private int vertexCount;
        private int triangleCount;
        private EntityManager em;
        private EntityArchetype arVertex;
        private EntityArchetype arTriangle;
        private EntityQuery qVertexComp;
        private EntityQuery qTriangleComp;

        #endregion

        #region METHODS --------------------------------------------------------

        protected override void OnUpdate()
        {
            Debug.Log("1");
            //
            // Get data
            go = GameObject.FindGameObjectWithTag("tagHexSphereBuildGameObject");
            data = go.GetComponent<HexSphereBuildDataProxy>();
            worldSize = data.WorldSize;
            subdivisionsCount = data.SubdivisionsCount;
            raduis = data.Raduis;
            vertexCount = data.VertexCount;
            triangleCount = data.TriangleCount;
            //em = World.Active.EntityManager; TODO : TESTING REPLACING WITH DstEntityManager

            //
            // First destroy existing entities
            var qTileComp = new EntityQueryDesc
            {
                Any = new ComponentType[] { ComponentType.ReadOnly<TileTriangleComponent>(), ComponentType.ReadOnly<TileVertexComponent>() },
                None = Array.Empty<ComponentType>(),
                All = Array.Empty<ComponentType>(),
            };
            DstEntityManager.DestroyEntity(DstEntityManager.CreateEntityQuery(qTileComp));

            var qVertTri = new EntityQueryDesc
            {
                Any = new ComponentType[] { ComponentType.ReadOnly<VertexComponent>(), ComponentType.ReadOnly<TriangleComponent>() },
                None = Array.Empty<ComponentType>(),
                All = Array.Empty<ComponentType>(),
            };
            DstEntityManager.DestroyEntity(DstEntityManager.CreateEntityQuery(qVertTri));

            //
            // Create Persistent data
            HexSphereBuildData.Verticies = new NativeArray<VertexComponent>(vertexCount, Allocator.Persistent);
            HexSphereBuildData.Triangles = new NativeArray<TriangleComponent>(triangleCount, Allocator.Persistent);

            //
            // Build data
            HexSphereBuildUtils.BuildHexSphereSystem(subdivisionsCount, raduis, ref HexSphereBuildData.Verticies, ref HexSphereBuildData.Triangles);

            //
            // Create Entity Archetype instantiation
            arVertex = DstEntityManager.CreateArchetype(typeof(VertexComponent), typeof(TileVertexComponent));
            arTriangle = DstEntityManager.CreateArchetype(typeof(TriangleComponent), typeof(TileTriangleComponent));

            //
            // Batch create entities
            NativeArray<Entity> eVertces = new NativeArray<Entity>(vertexCount, Allocator.TempJob);
            NativeArray<Entity> enTriangles = new NativeArray<Entity>(triangleCount, Allocator.TempJob);
            DstEntityManager.CreateEntity(arVertex, eVertces);
            DstEntityManager.CreateEntity(arTriangle, enTriangles);

            //
            // Create Entity EntityQuery
            qVertexComp = DstEntityManager.CreateEntityQuery(ComponentType.ReadOnly<VertexComponent>());
            qTriangleComp = DstEntityManager.CreateEntityQuery(ComponentType.ReadOnly<TriangleComponent>());

            //
            // Batch Set entity component data
            qVertexComp.CopyFromComponentDataArray<VertexComponent>(HexSphereBuildData.Verticies);
            qTriangleComp.CopyFromComponentDataArray<TriangleComponent>(HexSphereBuildData.Triangles);

            //
            // Cleanup
            eVertces.Dispose();
            enTriangles.Dispose();
            HexSphereBuildData.Verticies.Dispose();
            HexSphereBuildData.Triangles.Dispose();

        }

        #endregion
    }
}

I haven’t used subscenes in a while, but I suspect simply creating some entities in a system is not going to cause your entities to be serialized.

Newly created entities in the Destination world need to be associated with the source game object.
So you need to use:

See
var entity = GetPrimaryEntity(meshRenderer);
or
var meshEntity = CreateAdditionalEntity(meshRenderer);

MeshRendererConversion.cs as an example
To create the entity, then you can add any component data to it you like.

1 Like

I see, thanks for the help

OK So I got it all serializing correctly with the script below but it is running so soooo much slower. Is there a way to create additional entities in batch like I had and associated with the source game object?

using Unity.Collections;
using Unity.Entities;
using System;
using UnityEngine;
using Unity.Mathematics;


namespace Lightbringer.HexWorld
{
    /// <summary>
    /// This class is what builds the entity cache through sub scenes.
    /// It converts hexSphera vertex and triangle data to entity data.
    /// </summary>
    [UpdateAfter(typeof(HexSphereBuildDataConversion))]
    public class HexSphereBuildConversionSystem : GameObjectConversionSystem
    {
        #region FLIELDS --------------------------------------------------------

        private GameObject go;
        private HexSphereBuildDataProxy data;
        internal WORLD_SIZE worldSize;
        private int subdivisionsCount;
        private int raduis;
        private int vertexCount;
        private int triangleCount;
        private EntityManager em;
        private EntityArchetype arVertex;
        private EntityArchetype arTriangle;
        private EntityQuery qVertexComp;
        private EntityQuery qTriangleComp;

        #endregion

        #region METHODS --------------------------------------------------------

        protected override void OnUpdate()
        {
            Debug.Log("1");
            //
            // Get data
            go = GameObject.FindGameObjectWithTag("tagHexSphereBuildGameObject");
            data = go.GetComponent<HexSphereBuildDataProxy>();
            worldSize = data.WorldSize;
            subdivisionsCount = data.SubdivisionsCount;
            raduis = data.Raduis;
            vertexCount = data.VertexCount;
            triangleCount = data.TriangleCount;
            //em = World.Active.EntityManager; TODO : TESTING REPLACING WITH DstEntityManager
            //var e = GetPrimaryEntity(go);//TEST

            //
            // First destroy existing entities
            var qTileComp = new EntityQueryDesc
            {
                Any = new ComponentType[] { ComponentType.ReadOnly<TileTriangleComponent>(), ComponentType.ReadOnly<TileVertexComponent>() },
                None = Array.Empty<ComponentType>(),
                All = Array.Empty<ComponentType>(),
            };
            DstEntityManager.DestroyEntity(DstEntityManager.CreateEntityQuery(qTileComp));

            var qVertTri = new EntityQueryDesc
            {
                Any = new ComponentType[] { ComponentType.ReadOnly<VertexComponent>(), ComponentType.ReadOnly<TriangleComponent>() },
                None = Array.Empty<ComponentType>(),
                All = Array.Empty<ComponentType>(),
            };
            DstEntityManager.DestroyEntity(DstEntityManager.CreateEntityQuery(qVertTri));

            //
            // Create Persistent data
            HexSphereBuildData.Verticies = new NativeArray<VertexComponent>(vertexCount, Allocator.Persistent);
            HexSphereBuildData.Triangles = new NativeArray<TriangleComponent>(triangleCount, Allocator.Persistent);

            //
            // Build data
            HexSphereBuildUtils.BuildHexSphereSystem(subdivisionsCount, raduis, ref HexSphereBuildData.Verticies, ref HexSphereBuildData.Triangles);

            ////
            //// Create Entity Archetype instantiation
            //arVertex = DstEntityManager.CreateArchetype(typeof(VertexComponent), typeof(TileVertexComponent));
            //arTriangle = DstEntityManager.CreateArchetype(typeof(TriangleComponent), typeof(TileTriangleComponent));

            ////
            //// Batch create entities
            //NativeArray<Entity> eVertces = new NativeArray<Entity>(vertexCount, Allocator.TempJob);
            //NativeArray<Entity> enTriangles = new NativeArray<Entity>(triangleCount, Allocator.TempJob);
            //DstEntityManager.CreateEntity(arVertex, eVertces);
            //DstEntityManager.CreateEntity(arTriangle, enTriangles);

            ////
            //// Create Entity EntityQuery
            //qVertexComp = DstEntityManager.CreateEntityQuery(ComponentType.ReadOnly<VertexComponent>());
            //qTriangleComp = DstEntityManager.CreateEntityQuery(ComponentType.ReadOnly<TriangleComponent>());

            ////
            //// Batch Set entity component data
            //qVertexComp.CopyFromComponentDataArray<VertexComponent>(HexSphereBuildData.Verticies);
            //qTriangleComp.CopyFromComponentDataArray<TriangleComponent>(HexSphereBuildData.Triangles);


            //TEST
            for (var i = 0; i < vertexCount; i++)
            {
                var e = CreateAdditionalEntity(go);

                //DstEntityManager.AddComponentData(e, HexSphereBuildData.Verticies[i]);

                var vertexData = new VertexComponent
                {
                    PositionX = HexSphereBuildData.Verticies[i].PositionX,
                    PositionY = HexSphereBuildData.Verticies[i].PositionY,
                    PositionZ = HexSphereBuildData.Verticies[i].PositionZ,
                    ConnectedTriA = HexSphereBuildData.Verticies[i].ConnectedTriA,
                    ConnectedTriB = HexSphereBuildData.Verticies[i].ConnectedTriB,
                    ConnectedTriC = HexSphereBuildData.Verticies[i].ConnectedTriC,
                    ConnectedTriD = HexSphereBuildData.Verticies[i].ConnectedTriD,
                    ConnectedTriE = HexSphereBuildData.Verticies[i].ConnectedTriE,
                    ConnectedTriF = HexSphereBuildData.Verticies[i].ConnectedTriF
                };

                this.DstEntityManager.AddComponentData(e, vertexData);

                var vertexTileData = new TileVertexComponent
                {
                    Position = new float3(0,0,0),
                    ConnectedTriA = Entity.Null,
                    ConnectedTriB = Entity.Null,
                    ConnectedTriC = Entity.Null,
                    ConnectedTriD = Entity.Null,
                    ConnectedTriE = Entity.Null,
                    ConnectedTriF = Entity.Null
                };

                this.DstEntityManager.AddComponentData(e, vertexTileData);
            }

            for (var i = 0; i < triangleCount; i++)
            {
                var e = CreateAdditionalEntity(go);

                //DstEntityManager.AddComponentData(e, HexSphereBuildData.Verticies[i]);

                var triangleData = new TriangleComponent
                {
                    VertA = HexSphereBuildData.Triangles[i].VertA,
                    VertB = HexSphereBuildData.Triangles[i].VertB,
                    VertC = HexSphereBuildData.Triangles[i].VertC,
                    CenterVertex = HexSphereBuildData.Triangles[i].CenterVertex,
                    NeighborsAccrossAB = HexSphereBuildData.Triangles[i].NeighborsAccrossAB,
                    NeighborsAccrossBC = HexSphereBuildData.Triangles[i].NeighborsAccrossBC,
                    NeighborsAccrossCA = HexSphereBuildData.Triangles[i].NeighborsAccrossCA,
                    CenterPosition = HexSphereBuildData.Triangles[i].CenterPosition
                };

                this.DstEntityManager.AddComponentData(e, triangleData);


                var tileTriangleData = new TileTriangleComponent
                {
                    VertA = Entity.Null,
                    VertB = Entity.Null,
                    VertC = Entity.Null,
                    NeighborsAccrossAB = Entity.Null,
                    NeighborsAccrossBC = Entity.Null,
                    NeighborsAccrossCA = Entity.Null,
                    CenterPosition = new float3(0, 0, 0)
                };

                this.DstEntityManager.AddComponentData(e, tileTriangleData);


            }



            //
            // Cleanup
            //eVertces.Dispose();
            //         enTriangles.Dispose();
            HexSphereBuildData.Verticies.Dispose();
            HexSphereBuildData.Triangles.Dispose();

        }

        #endregion
    }
}

Wondering if someone could help me understand why my GameObjectConversionSystem run twice when I enter “Edit” mode and “Rebuild Entity Cache”.

You are definitely doing this wrong… Please follow MeshRendererConversion.cs as an example.

  • GameObject.FindGameObjectWithTag being used
  • There being state on the system which is dependent on the data in the scene
    Points to the code being incorrect.

I started rewriting this looking at MeshRenderConversion.cs but Im confused. So what Im tying to achieve is convert a GameObject with Component of type to entities and add addition entities with additional component data not on the GameObject. Pretty much exactly what MeshRenderConversion.cs is doing but what im not understanding is this:

MeshRenderConversion.cs has

Entities.ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) =>
 {
...
}

But where are the entities created ?

  1. My additional entities does not belong to any gameObject they are just data. What should pass to GetPrimaryEntity(?) and how do I get a gameObject to associate if I should not be using FindGameObjectWithTag
var entity = GetPrimaryEntity(meshRenderer);

I think im missing a lot here but hop to fill the knowledge gap

OK took a step back and tried to write a simple GameObjectConversionSystem. I know this doesnt work but hoping someone can take a looks and teach me.

Still using GameObject.FindGameObjectWithTag(), not sure how to get the GameObject the correct way to pass to GetPrimaryEntity.

GetPrimaryEntity() returns a “NullReferenceException: Object reference not set to an instance of an object”

This is as far as I got digging thought the examples

namespace Lightbringer.HexWorld
{
    public class HexSphereBuildDataConversion : GameObjectConversionSystem
    {
            go = GameObject.FindGameObjectWithTag("tagHexSphereBuildGameObject");
            data = go.GetComponent<HexSphereBuildDataProxy>();

            Entities.ForEach((HexSphereBuildDataProxy data) =>
            {

                var entity = GetPrimaryEntity(go);    
                //var entity = CreateAdditionalEntity(data);

                var componentData = new HexSphereBuildDataComponent
                {
                    WorldSize = data.WorldSize,
                    SubdivisionsCount = data.SubdivisionsCount,
                    Raduis = data.Raduis,
                    VertexCount = data.VertexCount,
                    TriangleCount = data.TriangleCount
                };

               DstEntityManager.AddComponentData(entity, componentData);
                Debug.Log(go.name + " //// TEST");
            });

        }
    }
}

what is this?

go = GameObject.FindGameObjectWithTag("tagHexSphereBuildGameObject");
data = go.GetComponent<HexSphereBuildDataProxy>();

Entities.ForEach((HexSphereBuildDataProxy data) =>

what are you attempting to do with the go/data doing before you do a entities foreach

-edit-

you’re way over-complicating this. all you need is this

public class HexSphereBuildDataConversion : GameObjectConversionSystem
{
    protected override void OnUpdate()
    {
        Entities.ForEach((HexSphereBuildDataProxy data) =>
        {
            var entity = GetPrimaryEntity(data);  
        }
    }
}

It where I started, but I keep getting a null reference exception. I just dont understand how data can exist anywhere appart from on the gameObject. Am I suppose to implement a system prior to this creating the data?

Edit : did a sanity check, just ran the code above praying it would work but still gettng a null reference exception on GetPrimaryEntity.

I just setup a scene and ran the code I posted and it works fine. I don’t know what you’re doing wrong.

using UnityEngine;

public class HexSphereBuildDataProxy  : MonoBehaviour
{
    public int ExtraEntities;
}

public class HexSphereBuildDataConversion : GameObjectConversionSystem
{
    protected override void OnUpdate()
    {
        this.Entities.ForEach((HexSphereBuildDataProxy data) =>
        {
            var entity = this.GetPrimaryEntity(data);
            Debug.Log(data.gameObject);
            Debug.Log($"Primary: {entity}");

            for (var i = 0; i < data.ExtraEntities; i++)
            {
                var extraEntity = this.CreateAdditionalEntity(data);
                Debug.Log($"Extra: {extraEntity}");
            }
        });
    }
}

MainScene:

SubScene:

Result:

4895663--473369--upload_2019-8-26_14-55-9.png

What the hell , ok let me go through all the code again … Thanks heaps for the example … it give me hope