Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Problem in RenderMesh sortings

Discussion in 'Graphics for ECS' started by od3098, Oct 3, 2019.

  1. od3098

    od3098

    Joined:
    Apr 29, 2015
    Posts:
    56
    I am writing a convertor to covert SpriteRenderer gameobjects to entity with RenderMesh component.

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Rendering;
    3. using Unity.Transforms;
    4. using UnityEngine;
    5.  
    6. namespace OpenEcsTools
    7. {
    8.     [DisallowMultipleComponent]
    9.     public class ConvertSpriteToEntity : MonoBehaviour
    10.     {
    11.         private EntityManager entityManager;
    12.         private void Awake()
    13.         {
    14.             // access the active entity manager
    15.             entityManager = World.Active.EntityManager;
    16.             // search through all childs of this object
    17.             foreach (Transform child in transform)
    18.             {
    19.                 int childComponentCount = child.GetComponents<Component>().Length;
    20.                 // if we are checking the current object and it only
    21.                 // has a transform and this component, ignore making an entity
    22.                 if (child == this && childComponentCount == 2) continue;
    23.  
    24.                 // if the child only has a transform component, dont convert it to entity
    25.                 if (childComponentCount == 1)
    26.                 {
    27.                     Debug.Log(string.Format("Ignore onverting {0}, it is an empty game object", child.name));
    28.                 }
    29.                 else
    30.                 {
    31.  
    32.                     // create a new entity for each child
    33.                     var entity = entityManager.CreateEntity();
    34.  
    35.                     // set entity name to its game object name
    36.                     entityManager.SetName(entity, gameObject.name + "/" + child.gameObject.name);
    37.  
    38.                     SpriteRenderer spriteRenderer = child.GetComponent<SpriteRenderer>();
    39.                     if (spriteRenderer != null)
    40.                     {
    41.                         Sprite sprite = spriteRenderer.sprite;
    42.  
    43.                         // create a new mesh for each sprite renderer
    44.                         var newMesh = new Mesh();
    45.  
    46.                         // create vector3 array for all vertices and copy from sprite renderers sprite vertices
    47.                         Vector3[] vertices = new Vector3[sprite.vertices.Length];
    48.                         for (int i = 0; i < sprite.vertices.Length; i++)
    49.                             vertices[i] = sprite.vertices[i];
    50.  
    51.                         // assign vertices to the new mesh
    52.                         newMesh.vertices = vertices;
    53.  
    54.                         // create a new int[] for all triangles same as what we did for vertices
    55.                         int[] triangles = new int[sprite.triangles.Length];
    56.                         for (int i = 0; i < sprite.triangles.Length; i++)
    57.                             triangles[i] = sprite.triangles[i];
    58.  
    59.                         // assign tirangles to mesh
    60.                         newMesh.triangles = triangles;
    61.  
    62.                         // assign sprite uv to mesh uv
    63.                         newMesh.uv = sprite.uv;
    64.  
    65.                         // Add local to world component, RenderMesh component needs this to show its mesh
    66.                         entityManager.AddComponentData<LocalToWorld>(entity, new LocalToWorld());
    67.  
    68.                         // assign a material
    69.                         Material newMaterial = new Material(spriteRenderer.sharedMaterial);
    70.                         newMaterial.mainTexture = sprite.texture;
    71.                         newMaterial.color = spriteRenderer.color;
    72.  
    73.                         // Add render mesh component to new entity
    74.                         entityManager.AddSharedComponentData<RenderMesh>(entity, new RenderMesh()
    75.                         {
    76.                             material = newMaterial,
    77.                             mesh = newMesh,
    78.                             castShadows = UnityEngine.Rendering.ShadowCastingMode.Off,
    79.                             receiveShadows = false,
    80.                             layer = spriteRenderer.sortingOrder
    81.                         });
    82.  
    83.                         // add translation component to new entity
    84.                         entityManager.AddComponentData<Translation>(entity, new Translation()
    85.                         {
    86.                             Value = new Unity.Mathematics.float3(
    87.                                 child.position.x,
    88.                                 child.position.y,
    89.                                 -spriteRenderer.sortingOrder)
    90.                         });
    91.  
    92.                         // if sprite is rotated, add rotation component too
    93.                         if (child.rotation != Quaternion.identity)
    94.                             entityManager.AddComponentData<Rotation>(entity, new Rotation() { Value = child.rotation });
    95.                     }
    96.                 }
    97.             }
    98.             Destroy(gameObject);
    99.         }
    100.     }
    101. }
    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:
    upload_2019-10-3_10-27-38.png


    PlayMode:
    upload_2019-10-3_10-26-22.png

    What am I missing here?

    Can you offer better ways to convert sprite renedrers to entities?
     
    Last edited: Oct 3, 2019
  2. OnceUponADev

    OnceUponADev

    Joined:
    Dec 5, 2018
    Posts:
    12
    I have the same issue, please let me know if you have managed to solved it!
     
  3. Radu392

    Radu392

    Joined:
    Jan 6, 2016
    Posts:
    210
    The current implementation of RenderMesh isn't a general purpose rendering system. It lacks many of the features you need in any specific use case, so your only option is to wait till Unity comes out with an update to it or write your own rendering system as most people on this forum have already done.

    An example:

    https://forum.unity.com/threads/spriterenderer-in-ecs.626437/
     
  4. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    The simplest way (not necessary best) is likely to ditch the hybrid tenderer and draw the sprites with drawmeshinstanced indirect.

    assuming your sprites all use the same material, you just have to draw the chunks in order of the layer value (since you assign The sorting layer, they are already split in different chunks)
     
    ph3rin likes this.
  5. OnceUponADev

    OnceUponADev

    Joined:
    Dec 5, 2018
    Posts:
    12
    thanks a lot for the solutions and answers, trying it now :)