Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Updating Meshes in Hybrid ECS

Discussion in 'Entity Component System' started by madks13, Jul 13, 2018.

  1. madks13

    madks13

    Joined:
    May 8, 2016
    Posts:
    173
    Hello,

    i'm trying to make a block(cube) spawn using hybrid ECS. I have a code that compiles and seem to work up to the part where i try to assign the updated mesh to the filter. It is never assigned, the filter always shows "None".
    Here is what the code looks like.

    The data class :
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class BlockData : MonoBehaviour
    4. {
    5.     //TextureIndex is a simple enum with integer values to find the texture UVs
    6.     public TextureIndex TextureIndex;
    7.     public bool RenderSides;
    8.     //Blockside is a Flag enum with a value for each side
    9.     //Front, Back, Left, Right, Top, Bottom
    10.     //It also has None and All for specific cases
    11.     public BlockSide FrontSide;
    12.     public BlockSide RenderingSides;
    13.     public bool Dirty;
    14. }
    15.  
    And the System :

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using Unity.Entities;
    3. using UnityEngine;
    4.  
    5. public class BlockSystem : ComponentSystem
    6. {
    7.     private struct Group
    8.     {
    9.         public Transform Transform;
    10.         public BlockData Data;
    11.         public MeshFilter Filter;
    12.         public MeshRenderer Renderer;
    13.     }
    14.  
    15.     protected override void OnUpdate()
    16.     {
    17.         List<UVTextureCoordinates> uvCoords = TextureTools.GetUVTextureCoordinates(16, 16);
    18.         foreach (var e in GetEntities<Group>())
    19.         {
    20.             if (e.Data.Dirty)
    21.             {
    22.                 UpdateBlock(e, uvCoords);
    23.                 e.Data.Dirty = false;
    24.             }
    25.         }
    26.     }
    27.  
    28.     private void UpdateBlock(Group e, List<UVTextureCoordinates> uvCoords)
    29.     {
    30.         var renderSides = e.Data.RenderSides;
    31.         var front = e.Data.FrontSide;
    32.         var side = e.Data.RenderingSides;
    33.         var filter = e.Filter;
    34.         var renderer = e.Renderer;
    35.         var transform = e.Transform;
    36.         var textureIndex = e.Data.TextureIndex;
    37.         Mesh mesh = filter.mesh;
    38.  
    39.         Debug.Log("Creating quad side " + side);
    40.         if (side.HasFlag(BlockSide.None))
    41.         {
    42.             return;
    43.         }
    44.  
    45.         if (mesh == null)
    46.         {
    47.             mesh = new Mesh();
    48.             mesh.name = "Scripted Mesh " + side;
    49.         }
    50.  
    51.         Vector3[] verts = new Vector3[4];
    52.         Vector3[] norms = new Vector3[4];
    53.         Vector2[] uvs = new Vector2[4];
    54.         int[] tris = new int[6];
    55.         Vector3 norm;
    56.         //Get the UV coordinates for the texture
    57.         UVTextureCoordinates coords = uvCoords[(int)textureIndex];
    58.  
    59.         uvs[0] = coords.UV00;
    60.         uvs[1] = coords.UV01;
    61.         uvs[2] = coords.UV11;
    62.         uvs[3] = coords.UV10;
    63.  
    64.         Draw(front, verts, out norm);
    65.         if (renderSides)
    66.         {
    67.  
    68.         }
    69.  
    70.         norms[0] = norm;
    71.         norms[1] = norm;
    72.         norms[2] = norm;
    73.         norms[3] = norm;
    74.  
    75.         tris[0] = 3;
    76.         tris[1] = 1;
    77.         tris[2] = 0;
    78.         tris[3] = 3;
    79.         tris[4] = 2;
    80.         tris[5] = 1;
    81.      
    82.         mesh.vertices = verts;
    83.         mesh.normals = norms;
    84.         mesh.uv = uvs;
    85.         mesh.triangles = tris;
    86.  
    87.         mesh.RecalculateBounds();
    88.  
    89.         e.Filter.mesh = null;
    90.         e.Filter.mesh = mesh;
    91.  
    92.     }
    93.  
    94.     private void Draw(BlockSide front, Vector3[] verts, out Vector3 norm)
    95.     {
    96.         switch (front)
    97.         {
    98.             case BlockSide.Top:
    99.                 norm = Vector3.up;
    100.  
    101.                 verts[0] = VerticesTools.GetPosition(CubeVerticePosition.BackTopLeft);
    102.                 verts[1] = VerticesTools.GetPosition(CubeVerticePosition.BackTopRight);
    103.                 verts[2] = VerticesTools.GetPosition(CubeVerticePosition.FrontTopRight);
    104.                 verts[3] = VerticesTools.GetPosition(CubeVerticePosition.FrontTopLeft);
    105.                 break;
    106.             case BlockSide.Left:
    107.                 norm = Vector3.left;
    108.  
    109.                 verts[0] = VerticesTools.GetPosition(CubeVerticePosition.BackTopLeft);
    110.                 verts[1] = VerticesTools.GetPosition(CubeVerticePosition.FrontTopLeft);
    111.                 verts[2] = VerticesTools.GetPosition(CubeVerticePosition.FrontBottomLeft);
    112.                 verts[3] = VerticesTools.GetPosition(CubeVerticePosition.BackBottomLeft);
    113.                 break;
    114.             case BlockSide.Right:
    115.                 norm = Vector3.right;
    116.  
    117.                 verts[0] = VerticesTools.GetPosition(CubeVerticePosition.FrontTopRight);
    118.                 verts[1] = VerticesTools.GetPosition(CubeVerticePosition.BackTopRight);
    119.                 verts[2] = VerticesTools.GetPosition(CubeVerticePosition.BackBottomRight);
    120.                 verts[3] = VerticesTools.GetPosition(CubeVerticePosition.FrontBottomRight);
    121.                 break;
    122.             case BlockSide.Bottom:
    123.                 norm = Vector3.down;
    124.  
    125.                 verts[0] = VerticesTools.GetPosition(CubeVerticePosition.FrontBottomLeft);
    126.                 verts[1] = VerticesTools.GetPosition(CubeVerticePosition.FrontBottomRight);
    127.                 verts[2] = VerticesTools.GetPosition(CubeVerticePosition.BackBottomRight);
    128.                 verts[3] = VerticesTools.GetPosition(CubeVerticePosition.BackBottomLeft);
    129.                 break;
    130.             case BlockSide.Front:
    131.                 norm = Vector3.forward;
    132.  
    133.                 verts[0] = VerticesTools.GetPosition(CubeVerticePosition.FrontTopLeft);
    134.                 verts[1] = VerticesTools.GetPosition(CubeVerticePosition.FrontTopRight);
    135.                 verts[2] = VerticesTools.GetPosition(CubeVerticePosition.FrontBottomRight);
    136.                 verts[3] = VerticesTools.GetPosition(CubeVerticePosition.FrontBottomLeft);
    137.                 break;
    138.             case BlockSide.Back:
    139.                 norm = Vector3.back;
    140.  
    141.                 verts[0] = VerticesTools.GetPosition(CubeVerticePosition.BackTopRight);
    142.                 verts[1] = VerticesTools.GetPosition(CubeVerticePosition.BackTopLeft);
    143.                 verts[2] = VerticesTools.GetPosition(CubeVerticePosition.BackBottomLeft);
    144.                 verts[3] = VerticesTools.GetPosition(CubeVerticePosition.BackBottomRight);
    145.                 break;
    146.             default:
    147.                 norm = Vector3.zero;
    148.                 break;
    149.         }
    150.     }
    151. }
    152.  
    I saw on some older posts that some parts of Mesh manipulation isn't accessible trough ECS, but i have no idea if it still is the same or the parts i need to make this work are already available.

    Can anyone help?
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    https://github.com/keijiro/Firefly

    Check out this demo. What I used as a foundation for my voxel world.

    Long story short, you can manipulate meshes in jobs just requires some tricks
     
  3. madks13

    madks13

    Joined:
    May 8, 2016
    Posts:
    173
    Thanks, will take a look when i can.

    Edit :

    I had time to do a quick check of your project. Correct me if i'm wrong but the part that might help me is :

    Code (CSharp):
    1.  
    2.                 // Draw call
    3.                 UnityEngine.Graphics.DrawMesh(
    4.                     mesh, identityMatrix, renderer.Settings.Material, 0
    5.                 );
    If i uderstood this right, this is the part that would draw the mesh. However, i used a hybrid ECS to have the Physics for collision checks. Does your project tackle that part too?
     
    Last edited: Jul 15, 2018