I am writing a convertor to covert SpriteRenderer gameobjects to entity with RenderMesh component.
using Unity.Entities;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;
namespace OpenEcsTools
{
[DisallowMultipleComponent]
public class ConvertSpriteToEntity : MonoBehaviour
{
private EntityManager entityManager;
private void Awake()
{
// access the active entity manager
entityManager = World.Active.EntityManager;
// search through all childs of this object
foreach (Transform child in transform)
{
int childComponentCount = child.GetComponents<Component>().Length;
// if we are checking the current object and it only
// has a transform and this component, ignore making an entity
if (child == this && childComponentCount == 2) continue;
// if the child only has a transform component, dont convert it to entity
if (childComponentCount == 1)
{
Debug.Log(string.Format("Ignore onverting {0}, it is an empty game object", child.name));
}
else
{
// create a new entity for each child
var entity = entityManager.CreateEntity();
// set entity name to its game object name
entityManager.SetName(entity, gameObject.name + "/" + child.gameObject.name);
SpriteRenderer spriteRenderer = child.GetComponent<SpriteRenderer>();
if (spriteRenderer != null)
{
Sprite sprite = spriteRenderer.sprite;
// create a new mesh for each sprite renderer
var newMesh = new Mesh();
// create vector3 array for all vertices and copy from sprite renderers sprite vertices
Vector3[] vertices = new Vector3[sprite.vertices.Length];
for (int i = 0; i < sprite.vertices.Length; i++)
vertices[i] = sprite.vertices[i];
// assign vertices to the new mesh
newMesh.vertices = vertices;
// create a new int[] for all triangles same as what we did for vertices
int[] triangles = new int[sprite.triangles.Length];
for (int i = 0; i < sprite.triangles.Length; i++)
triangles[i] = sprite.triangles[i];
// assign tirangles to mesh
newMesh.triangles = triangles;
// assign sprite uv to mesh uv
newMesh.uv = sprite.uv;
// Add local to world component, RenderMesh component needs this to show its mesh
entityManager.AddComponentData<LocalToWorld>(entity, new LocalToWorld());
// assign a material
Material newMaterial = new Material(spriteRenderer.sharedMaterial);
newMaterial.mainTexture = sprite.texture;
newMaterial.color = spriteRenderer.color;
// Add render mesh component to new entity
entityManager.AddSharedComponentData<RenderMesh>(entity, new RenderMesh()
{
material = newMaterial,
mesh = newMesh,
castShadows = UnityEngine.Rendering.ShadowCastingMode.Off,
receiveShadows = false,
layer = spriteRenderer.sortingOrder
});
// add translation component to new entity
entityManager.AddComponentData<Translation>(entity, new Translation()
{
Value = new Unity.Mathematics.float3(
child.position.x,
child.position.y,
-spriteRenderer.sortingOrder)
});
// if sprite is rotated, add rotation component too
if (child.rotation != Quaternion.identity)
entityManager.AddComponentData<Rotation>(entity, new Rotation() { Value = child.rotation });
}
}
}
Destroy(gameObject);
}
}
}
I have used spriteRenderer.sortingOrder value for RenderMesh.layer.
The problem is that object render sorting will not care about this parameter and each gameObject has higher position in hierarchy will be render over others.
I also tried to bring front entities near the camera in Z axis but they will render under the background.
Editor:
PlayMode:
What am I missing here?
Can you offer better ways to convert sprite renedrers to entities?