Help needed: ConvertToEntity works but SubScene does not for SharedComponentData

I have written a converter for the SpriteRenderer that looks as follows:

public class SpriteRendererConverter : MonoBehaviour, IConvertGameObjectToEntity
{
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        var spriteRenderer = GetComponent<SpriteRenderer>();
        var sprite = spriteRenderer.sprite;
        var mesh = new Mesh() {
            vertices = Array.ConvertAll(sprite.vertices, x => (Vector3)x),
            triangles = Array.ConvertAll(sprite.triangles, x => (int)x),
            uv = sprite.uv
        };
        dstManager.AddComponentData(entity, new PerInstanceRenderInfo
        {
            Tint = spriteRenderer.color,
            Layer = gameObject.layer
        });
        dstManager.AddSharedComponentData(entity, new SharedSprite
        {
            Value = sprite
        });
        dstManager.AddSharedComponentData(entity, new SharedMesh
        {
            Value = mesh
        });
    }
}

This works fine when I’m attaching the ConvertToEntity script. But when I want to create a subscene out of a gameobject it throws the following error:

ArgumentException: SharedMesh has no valid proxy shared component data. Please create one.The problem seems to be with SharedComponentData in general; when I comment out SharedMesh it throws the same error with SharedSprite.

As far as my understanding goes Proxies are deprecated, so I’m unsure if this error is even correct. I was also unable to find any information about how exactly Proxies are supposed to be implemented.
Providing simple stubs like:

public class SharedMeshProxy : SharedComponentDataProxy<SharedMesh>{}prevents the errors but doesn’t make it work correctly.
Does anyone have a clue what it is that I’m doing wrong and how to fix it?

1 Like

Same issue here. I just ran it to it. I had the item in my main scene, but when I moved it to the sub scene and removed Convert To Entity, I got this error. Remove the SharedComponentData and it works.

1 Like

Show your shared component declaration.

I figured it out. The problem is the way ISharedComponentData is Serialized.

Because the problem is serialisation and the ConvertToEntity workflow works at runtime they never collide, the subscene is superior because the heavy lifting for conversion can be done at editor time, but this leads to the need to serialize the data.

The requirements for ISharedComponentData (that I’ve found) is that you have a class called “{YourSharedComponent}Proxy” which inherits from “SharedComponentDataProxy<{YourSharedComponent}>” (it can be completely empty). This Proxy class has to be in a file called “{YourSharedComponent}Proxy.cs”. In addition to this your shared component also has to have the “[System.Serializable]” attribute. It’s easiest to pack both your component as well as the proxy in the same file and call it the name of the proxy class.

As straightforward example of a serializable ISharedComponentData would be this script in a file called “SharedSpriteProxy.cs”:

using System;
using Unity.Entities;
using UnityEngine;

[Serializable]
public struct SharedSprite : ISharedComponentData, IEquatable<SharedSprite>
{
    public Sprite Value;

    //insert object equals, SharedSprite equals, GetHashCode, == and != functions
}


public class SharedSpriteProxy : SharedComponentDataProxy<SharedSprite>
{}

It would be really nice if the file name and proxy class requirements would go in the future or be generated in the background where you don’t have to worry about them.

2 Likes

As you have found out, the serializer is quite out of date and still uses SharedComponentDataProxy to handle ISharedComponentData. Don’t expect SharedComponentDataProxy to hang around though. It’s part of the old GameObjectEntity workflow that while isn’t technically depreciated yet will be removed at some point.

I’m hoping the next version removes this dependency as it’s been 8 months since conversion workflow as was added.

3 Likes

All I needed was a sleep, was so annoyed I couldn’t figure this out last night!
Thanks @tertle and @TotallyRonja for the info/updates.

Thank you all so much for the quick help! I was able to solve my problem and get subscenes to work :slight_smile:

I really wish this was documented better - or at all actually…
I found some other curiosities that might help people searching for this problem so here goes:

Serializing meshes did not work, probably because they are cleaned up since they don’t have another reference to them. Saving them into a serialized field on the conversion script unfortunately didn’t help either. The solution was to just generate the mesh at runtime and add the SharedComponent then.

The subscene will take some time to load and does so without stalling the main thread. So not seeing anything for the first few frames is normal. This is kind of documented in that there are forum entries talking about it - adding that to the sparse documentation of SubScene would be a start though…as would be having a direct callback when its done loading.