ECS and material instancing

Hello,

I have a scene with a few thousand GameObjects that I’ve converted to ECS. All of the objects use the same shader, but they each get a unique combination of three properties on the shader, which, in the old GameObject world just automatically causes material instancing.

With ECS, the only way I have managed to preserve unique material properties on each entity is by spawning them one by one, like so:

GameObject obj = GameObject.Instantiate(prefab, ...);
obj.GetComponent<SpriteRenderer>().material.SetColor(...) // And so on...
GameObjectConversionUtility.ConvertGameObjectHierarchy(obj, ...)
GameObject.Destroy(obj)

This works for me, because I only spawn all of these objects once, but it’s obviously pretty wasteful.

I guess I have two questions:

  • There doesn’t seem to be a SpriteRenderer ISharedComponentData or similar, even though I can see it in the Entity Debugger. Can I access the material data of an existing entity?
  • Is having ~1000-2000 material instances a bad idea that Unity is trying to save me from? The graphics card seems to be happy even with 10-20x more.

As an aside, I have tried using Hybrid Renderer V2, which theoretically allows material property overrides, but it really doesn’t seem to be ready for production. Does that handle varying material properties differently?

Here you go: DOTS Hybrid Renderer | Hybrid Renderer | 0.4.2-preview.16

Thanks for that link, but that’s the Hybrid Renderer V2 thing I was talking about. I’m fine with being an early adopter, but that package really doesn’t seem ready. (I tried to get it to work, but the errors just seemed endless, and every time I fixed one, two more appeared.)

I’m still curious if there’s a way to get at the components like SpriteRenderer, which the Entity Debugger can see, but I can’t find the struct for?

EntityManager.GetComponentObject<>() is probably what you are looking for. It can access things like MonoBehaviours which are hidden by AddHybridComponent()

Hey, that worked, thanks!

I am confused how to do it? i want to update material property at run time ,
but when i use

 var material = EntityManager.GetComponentObject<Material>(entity);
                    Debug.Log(material.color);

it will show:
ArgumentException: A component with type:UnityEngine.Material has not been added to the entity.

Any answers?

Is there a reason you aren’t using Material Property Components? https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/GraphicsSamples/URPSamples/Assets/SampleScenes/MaterialOverridesSample