Entities not being rendered

I am creating a prototype Entity in a monobehavior and then instantiating that entity and assigning it the necessary components to then assign a mesh using a SystemBase. I can also see the entities with the necessary components in the Entity hierarchy. Here are the relevant code pieces:

    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player").transform;
        currentPlayerChunk = GetChunkCoordinateFromPosition(player.position);

        var desc = new RenderMeshDescription(shadowCastingMode: ShadowCastingMode.Off, receiveShadows: false);
        var renderMeshArray = new RenderMeshArray(new Material[] { material }, new Mesh[] { new Mesh() });

        prototype = entityManager.CreateEntity(); // create prototype 

        RenderMeshUtility.AddComponents(
            prototype,
            entityManager,
            desc,
            renderMeshArray,
            MaterialMeshInfo.FromRenderMeshArrayIndices(0, 0));
        entityManager.AddComponentData(prototype, new LocalToWorld());


        using (var builder = new BlobBuilder(Allocator.Temp))
        {
            ref var meshData = ref builder.ConstructRoot<MeshData>();
            var verticesArray = builder.Allocate(ref meshData.Vertices, vertexPool.Length);
            var trianglesArray = builder.Allocate(ref meshData.Triangles, trianglePool.Length);
            var uvsArray = builder.Allocate(ref meshData.UVs, uvPool.Length);

            for (int i = 0; i < vertexPool.Length; i++)
            {
                verticesArray[i] = vertexPool[i];
            }
            for (int i = 0; i < trianglePool.Length; i++)
            {
                trianglesArray[i] = trianglePool[i];
            }
            for (int i = 0; i < uvPool.Length; i++)
            {
                uvsArray[i] = uvPool[i];
            }

            var blobAsset = builder.CreateBlobAssetReference<MeshData>(Allocator.Persistent);

            entityManager.AddComponentData(prototype, new MeshComponent { MeshData = blobAsset });
            entityManager.AddComponentData(prototype, new Chunk { self = prototype, material = MaterialManager.GetMaterialIndex(material) });
        }

        UpdateChunks();
    }
void CreateTerrainChunkEntity(Vector2Int chunkCoord, NativeArray<Vector3> vertices, NativeArray<int> triangles, NativeArray<Vector2> uvs, int resolution, Material material)
{
    var ecb = new EntityCommandBuffer(Allocator.Temp, PlaybackPolicy.MultiPlayback);

    var chunkInstance = ecb.Instantiate(prototype);
    Debug.Log("Entity: " + chunkInstance + " has been spawned");

    BlobAssetReference<MeshData> blobAsset;
    using (var builder = new BlobBuilder(Allocator.Temp))
    {
        ref var meshData = ref builder.ConstructRoot<MeshData>();

        var verticesArray = builder.Allocate(ref meshData.Vertices, vertices.Length);
        var trianglesArray = builder.Allocate(ref meshData.Triangles, triangles.Length);
        var uvsArray = builder.Allocate(ref meshData.UVs, uvs.Length);

        for (int i = 0; i < vertices.Length; i++)
        {
            verticesArray[i] = vertices[i];
        }

        for (int i = 0; i < triangles.Length; i++)
        {
            trianglesArray[i] = triangles[i];
        }

        for (int i = 0; i < uvs.Length; i++)
        {
            uvsArray[i] = uvs[i];
        }
        blobAsset = builder.CreateBlobAssetReference<MeshData>(Allocator.Persistent);
    }

    ecb.AddComponent(chunkInstance, new MeshComponent { MeshData = blobAsset });
    ecb.AddComponent(chunkInstance, new Chunk { self = chunkInstance, material = MaterialManager.GetMaterialIndex(material) });
    ecb.AddComponent(chunkInstance, new LocalTransform { Position = new float3(chunkCoord.x * chunkSize, 0, chunkCoord.y * chunkSize) });
    //ecb.AddComponent(chunkInstance, new Parent { Value = parentEntity });
    ecb.SetName(chunkInstance, $"Chunk_{chunkCoord.x}_{chunkCoord.y}");
   
    ecb.Playback(entityManager);
    ecb.Dispose();
    //blobAsset.Dispose();
}
using Unity.Entities;
using Unity.Entities.Graphics;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;
using UnityEngine.Rendering;

public partial class ChunkSystem2 : SystemBase
{
    private EntitiesGraphicsSystem _entitiesGraphicsSystem;
    private EndSimulationEntityCommandBufferSystem _endSimulationEcbSystem;

    protected override void OnCreate()
    {
        RequireForUpdate<MeshComponent>();

        _endSimulationEcbSystem = World.GetOrCreateSystemManaged<EndSimulationEntityCommandBufferSystem>();
        _entitiesGraphicsSystem = World.GetOrCreateSystemManaged<EntitiesGraphicsSystem>();
    }

    protected override void OnUpdate()
    {
        var ecb = _endSimulationEcbSystem.CreateCommandBuffer().AsParallelWriter();
        foreach ((RefRO<MeshComponent> meshComponent, RefRO<Chunk> chunkData) in SystemAPI.Query<RefRO<MeshComponent>, RefRO<Chunk>>())
        {
            Debug.Log($"Entity World: {World.DefaultGameObjectInjectionWorld}");
            Mesh mesh = new Mesh
            {
                vertices = meshComponent.ValueRO.MeshData.Value.Vertices.ToArray(),
                triangles = meshComponent.ValueRO.MeshData.Value.Triangles.ToArray(),
                uv = meshComponent.ValueRO.MeshData.Value.UVs.ToArray()
            };
            Debug.Log($"Vertices Count: {mesh.vertexCount}, Triangles Count: {mesh.triangles.Length / 3}, UVs Count: {mesh.uv.Length}");
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

           // GameObject.Find("Sphere").GetComponent<MeshFilter>().mesh = mesh;

            //mesh = GenerateLargeGridMesh(1000, 1000);

            BatchMeshID meshID = _entitiesGraphicsSystem.RegisterMesh(mesh);

            Debug.Log(MaterialManager.GetMaterialByIndex(chunkData.ValueRO.material));

            var materialID = _entitiesGraphicsSystem.RegisterMaterial(MaterialManager.GetMaterialByIndex(chunkData.ValueRO.material));

            Entity chunk = chunkData.ValueRO.self;

            ecb.AddComponent<RenderMeshUnmanaged>(1, chunk, new RenderMeshUnmanaged
            {
                mesh = mesh
            });

            ecb.SetComponent<MaterialMeshInfo>(1, chunk, new MaterialMeshInfo
            {
                MaterialID = materialID,
                MeshID = meshID,
                 
            });
            Debug.Log($"Chunk Entity: {chunk.Index}");

            ecb.RemoveComponent<Chunk>(1, chunk);
        }
    }
}

Also here the shader:

Shader "Custom/Terrain2"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _GradientColor1 ("Gradient Color 1", Color) = (0, 0, 1, 1) // Blue
        _GradientColor2 ("Gradient Color 2", Color) = (0, 1, 0, 1) // Green
        _GradientColor3 ("Gradient Color 3", Color) = (1, 1, 0, 1) // Yellow
        _GradientColor4 ("Gradient Color 4", Color) = (1, 0, 0, 1) // Red
        _Height1 ("Height 1", Range(-256, 1024)) = 85
        _Height2 ("Height 2", Range(0, 1024)) = 170
        _Height3 ("Height 3", Range(0, 1024)) = 700
        _Height4 ("Height 4", Range(0, 1024)) = 1024
        _DetailTex1 ("Detail Texture 1", 2D) = "white" {}
        _DetailTex2 ("Detail Texture 2", 2D) = "white" {}
        _DetailTex3 ("Detail Texture 3", 2D) = "white" {}
        _DetailTex4 ("Detail Texture 4", 2D) = "white" {}
        _NoiseTex1 ("Noise Texture1", 2D) = "white" {}   // New noise texture
        _NoiseTex2 ("Noise Texture2", 2D) = "white" {}   // New noise texture
        _NoiseScale1 ("Noise Scale1", Range(0.1, 10.0)) = 1.0  // Noise scale control
        _NoiseScale2 ("Noise Scale2", Range(0.1, 100.0)) = 1.0  // Noise scale control
        _NoiseInfluence1 ("Noise Influence1", Range(0, 1)) = 0.5
        _NoiseInfluence2 ("Noise Influence2", Range(0, 1)) = 0.5
        _ColorFog ("Fog Color", Color) = (0.5, 0.5, 0.5, 1)
        _FogStartDistance ("Fog Start Distance", Range(0, 20000)) = 100
        _FogEndDistance ("Fog End Distance", Range(0, 20000)) = 300
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #pragma target 4.5
            #pragma instancing_options renderinglayer
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "HLSLSupport.cginc"

            CBUFFER_START(UnityPerMaterial)
            half4 _Color;
            half _Glossiness;
            half _Metallic;
            float4 _GradientColor1;
            float4 _GradientColor2;
            float4 _GradientColor3;
            float4 _GradientColor4;
            float _Height1;
            float _Height2;
            float _Height3;
            float _Height4;
            float _FogStartDistance;
            float _FogEndDistance;
            float4 _ColorFog;
            float _NoiseScale1;
            float _NoiseScale2;
            float _NoiseInfluence1;
            float _NoiseInfluence2;
            CBUFFER_END

            #if defined(UNITY_DOTS_INSTANCING_ENABLED)
                UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata) 
                    UNITY_DOTS_INSTANCED_PROP(float4, _Color)
                    UNITY_DOTS_INSTANCED_PROP(half, _Glossiness)
                    UNITY_DOTS_INSTANCED_PROP(half, _Metallic)
                    UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor1)
                    UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor2)
                    UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor3)
                    UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor4)
                    UNITY_DOTS_INSTANCED_PROP(float, _Height1)
                    UNITY_DOTS_INSTANCED_PROP(float, _Height2)
                    UNITY_DOTS_INSTANCED_PROP(float, _Height3)
                    UNITY_DOTS_INSTANCED_PROP(float, _Height4)
                    UNITY_DOTS_INSTANCED_PROP(float4, _ColorFog)
                    UNITY_DOTS_INSTANCED_PROP(float, _FogStartDistance)
                    UNITY_DOTS_INSTANCED_PROP(float, _FogEndDistance)
                    UNITY_DOTS_INSTANCED_PROP(float, _NoiseScale1)
                    UNITY_DOTS_INSTANCED_PROP(float, _NoiseScale2)
                    UNITY_DOTS_INSTANCED_PROP(float, _NoiseInfluence1)
                    UNITY_DOTS_INSTANCED_PROP(float, _NoiseInfluence2)
                UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)

                #define _Color UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _Color)
                #define _Glossiness UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(half, _Glossiness)
                #define _Metallic UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(half, _Metallic)
                #define _GradientColor1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor1)
                #define _GradientColor2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor2)
                #define _GradientColor3 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor3)
                #define _GradientColor4 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor4)
                #define _Height1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height1)
                #define _Height2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height2)
                #define _Height3 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height3)
                #define _Height4 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height4)
                #define _ColorFog UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _ColorFog)
                #define _FogStartDistance UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _FogStartDistance)
                #define _FogEndDistance UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _FogEndDistance)
                #define _NoiseScale1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseScale1)
                #define _NoiseScale2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseScale2)
                #define _NoiseInfluence1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseInfluence1)
                #define _NoiseInfluence2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseInfluence2)
            #endif

            sampler2D _MainTex;
            sampler2D _DetailTex1;
            sampler2D _DetailTex2;
            sampler2D _DetailTex3;
            sampler2D _DetailTex4;
            sampler2D _NoiseTex1;
            sampler2D _NoiseTex2;

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
                float3 position : TEXCOORD1;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionHCS : SV_POSITION;
                float height : TEXCOORD1;
                float3 normal : NORMAL;
                float3 worldPos : TEXCOORD2;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            Varyings vert(Attributes IN)
            {
                Varyings OUT;

                UNITY_SETUP_INSTANCE_ID(IN);
                UNITY_TRANSFER_INSTANCE_ID(IN, OUT);

                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);

                OUT.uv = IN.uv;
                OUT.height = IN.positionOS.y;

                float3 normal = float3(0.0, 1.0, 0.0); // Assume upwards-facing normal
                OUT.normal = normal;

                // Store the world position for fog calculations
                OUT.worldPos = IN.positionOS.xyz;

                return OUT;
            }


            fixed4 frag(Varyings i) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(i)
                //return float4(i.worldPos / 100.0, 1.0);

                float noiseValue1 = tex2D(_NoiseTex1, i.uv * _NoiseScale1).r;
                float noiseValue2 = tex2D(_NoiseTex2, i.uv * _NoiseScale2).r;

                float modifiedHeight = i.height + (noiseValue1 * _NoiseInfluence1 * 100) + (noiseValue2 * _NoiseInfluence2 * 100);

                float3 gradientColor;
                fixed4 detailColor;

                if (modifiedHeight < _Height1)
                {
                    gradientColor = _GradientColor1.rgb;
                    detailColor = tex2D(_DetailTex1, i.uv);
                }
                else if (modifiedHeight < _Height2)
                {
                    gradientColor = lerp(_GradientColor1.rgb, _GradientColor2.rgb, (modifiedHeight - _Height1) / (_Height2 - _Height1));
                    detailColor = tex2D(_DetailTex2, i.uv);
                }
                else if (modifiedHeight < _Height3)
                {
                    gradientColor = lerp(_GradientColor2.rgb, _GradientColor3.rgb, (modifiedHeight - _Height2) / (_Height3 - _Height2));
                    detailColor = tex2D(_DetailTex3, i.uv);
                }
                else if (modifiedHeight < _Height4)
                {
                    gradientColor = lerp(_GradientColor3.rgb, _GradientColor4.rgb, (modifiedHeight - _Height3) / (_Height4 - _Height3));
                    detailColor = tex2D(_DetailTex4, i.uv);
                }
                else
                {
                    gradientColor = _GradientColor4.rgb;
                    detailColor = tex2D(_DetailTex4, i.uv);
                }

                float3 lightDir = normalize(float3(1, 1, -1));
                float lightIntensity = max(dot(i.normal, lightDir), 0.0);

                float fogDistance = length(i.worldPos - _WorldSpaceCameraPos);
                float fogFactor = saturate((fogDistance - _FogStartDistance) / (_FogEndDistance - _FogStartDistance));

                fixed4 baseColor = tex2D(_MainTex, i.uv) * fixed4(gradientColor, 1.0) * _Color * detailColor * lightIntensity;
                fixed4 fogColor = fixed4(_ColorFog.rgb, 1.0);

                return lerp(baseColor, fogColor, fogFactor);
            }
            ENDHLSL
        }
    }
    FallBack "Diffuse"
}

My camera has everything on it’s culling layer, my entities do have a renderMeshUnmanaged, my vertex count is 289, my uv count is 289 my trianglecount/3 is 512 and my shader works on other baked entities.
So why am I not seeing anything beeing rendered? I even tried replacing the mesh with a custom grid mesh and it didn’t work.

I don’t know if it’s relevant but I also found out that my when my Camera looks at (0,0,0) but isn’t at (0,0,0) itself the tris count increases from like 4k to 500k. And generally the tris count even when not looking at (0,0,0) increases as I increase the renderdistance.

  1. You didn’t show code where you are actually setting the MeshData blob to the Mesh object.
  2. Have you tried assigning the exact same generated mesh to a normal GameObject?
  3. If it doesn’t work for (2) either, I suspect you might be encountering backface culling.
  4. Try using the frame debugger or renderdoc to ensure your entity is being rendered and to see what data it is using to render. Then check whether that data is correct.

This is where I set the blobAsset.
I tried applying the mesh to a sphere now after which Unity crashed. When I changed the material to the default and tried again it didn’t crash. When I switched it back it crashed again, so most likely it’s got something to do with the shader I guess. When I don’t use entities for the chunks it works just fine though

Vertices Count: 289, Triangles Count: 524288, UVs Count: 289
I just saw that the first time it logs the mesh the triangle count is ridiculously high. It probably has to do with how I create a blobassetreference with empty arrays for my prototype?

Did you define the component type MeshComponent? Because if so, Entities Graphics neither knows about nor cares about it. Until that data is in an actual Mesh object (the class Mesh) and that Mesh object is registered and referenced by MaterialMeshInfo, Entities Graphics won’t render it.

You’re right, I forgot to include the systemBase. I added it in the edit. I fixed the Triangle count, which was caused by not factoring in the resolution at the initial triangle calculation. I still can’t apply the terrain material to the sphere and change it’s mesh without it crashing though.

Okay. So let me get this straight so that I understand.

You’ve applied both the mesh and the material to a GameObject and it works?
You’ve applied just the mesh with a basic Lit material to an entity and it works?
You’ve applied just the material with some primitive mesh to an entity and it works?
You’ve applied both the mesh and material to an entity and Unity crashes?

Is this correct?

No, when I apply the mesh and the material to a Gameobject it crashes. My code is supposed to apply the meshes and material to the entity chunks, but I can’t see those at all. The frame Debugger also doesn’t show any of the entity chunks I think. When I create other entities though, they are shown, and when I apply the mesh to the sphere that is also shown

Okay. It sounds like multiple things are going wrong. Is anything going right?

What is your WorldRenderBounds of the entity?

Huh. That is a peculiarly-sized axis-aligned bounding box. That’s also a peculiar transform, with a lot of zeros, almost like some kind of black hole.

You should always check these things in the future when you run into rendering problems. They are super common mistakes to make with runtime meshes.

Ok I implemented this:
ecb.SetComponent(1, chunk, new RenderBounds
{
Value = mesh.bounds.ToAABB()
});
the world render bounds still stay at 0,0,0 though. I even have a render bounds system update

Got it to work. I wasn’t setting rotation and scale when adding the LocalTransform. Thanks for all the help!

The frustum culling is really weird though. It is culling the entities even as they are in the view

Does the WorldRenderBounds encapsulate the mesh in world space? If not, figure out why. WorldRenderBounds is computed from RenderBounds and LocalToWorld.

Yeah I figured it out. I was doing the bounds calculating wrong. Works perfectly fine now. Again, thank you for your help!