Hi,
for the last few days I’ve been trying to create a small, 2.5D, grid based proc-gen map using DOTS - Entities 0.51 (I have about some experience with GO based Unity workflow, but zero with DOTS). I have an issue with rendering my map tiles, here’s the rendering code:
[UpdateInGroup(typeof(PresentationSystemGroup))]
public partial class MapRendererSystem : SystemBase
{
public Mesh TileMesh;
public Material TileMaterial;
private bool _mapRendered = false;
protected override void OnUpdate()
{
if(_mapRendered)
{
return;
}
var ecb = new EntityCommandBuffer(Allocator.TempJob);
var renderMeshDescription = new RenderMeshDescription(
TileMesh,
TileMaterial,
shadowCastingMode: UnityEngine.Rendering.ShadowCastingMode.Off,
receiveShadows: false);
var tileQuery = EntityManager.CreateEntityQuery(new EntityQueryDesc
{
None = new ComponentType[] { typeof(RenderMesh) }, // just to be safe
All = new ComponentType[] { ComponentType.ReadOnly<TileComponent>() }
});
var tileEntities = tileQuery.ToEntityArray(Allocator.TempJob);
foreach(var entity in tileEntities)
{
RenderMeshUtility.AddComponents(
entity,
ecb,
renderMeshDescription);
EntityManager.AddComponentData(entity, new LocalToWorld());
}
//Dependency.Complete();
ecb.Playback(EntityManager);
tileEntities.Dispose();
tileQuery.Dispose();
ecb.Dispose();
//var renderTilesJob = new RenderTilesJob();
//var renderTilesJobHandle = renderTilesJob.ScheduleParallel();
//renderTilesJobHandle.Complete();
_mapRendered = true;
}
partial struct RenderTilesJob : IJobEntity
{
void Execute(ref LocalToWorld localToWorld, in TileComponent tile)
{
localToWorld.Value = ComputeTransform(tile);
}
private float4x4 ComputeTransform(TileComponent tile)
{
return float4x4.Translate(new float3(tile.Position.y, tile.Position.y, 0));
}
}
}
public struct TileComponent : IComponentData
{
public int2 Position;
public TileType TileType; // just an enum
}
so I have a few questions:
- the above code does generate entities with LocalToWorld, RenderMesh etc. components, however they do not actually appear in the game. If I uncomment the following part:
//var renderTilesJob = new RenderTilesJob();
//var renderTilesJobHandle = renderTilesJob.ScheduleParallel();
//renderTilesJobHandle.Complete();
then no HybridRender components get attached to the entities at all, only TileComponents are attached. What am I doing wrong?
- how should I properly load meshes and materials into SystemBase classes? I’m currently using a MonoBehaviour class like so:
public class MapRenderSystemFeeder : MonoBehaviour
{
public Mesh TileMesh;
public Material TileMaterial;
void Start()
{
var world = World.DefaultGameObjectInjectionWorld;
var mapRendererSystem = world.GetExistingSystem<MapRendererSystem>();
mapRendererSystem.TileMesh = TileMesh;
mapRendererSystem.TileMaterial = TileMaterial;
}
}
surely there is a better way? Initially I tried the GO approach, like this: Runtime entity creation | Hybrid Renderer | 0.51.1-preview.21 , however I’m not sure if this is correct for real-world games?
- How to make sure a System only does 1 cycle of work? I currently use this:
if(_mapRendered)
{
return;
}
to make sure the System only works once. But it’s probably wrong?