Files
Workspace/Assets/Demos/Demo2/Runtime/Demo2ItemBatchRenderer.cs
T
2026-08-18 02:03:34 +08:00

93 lines
3.9 KiB
C#

#nullable enable
using System.Collections.Generic;
using Demo2.Domain;
using Demo2.ECS;
using Unity.Collections;
using UnityEngine;
namespace Demo2.Runtime
{
public sealed class Demo2ItemBatchRenderer : MonoBehaviour
{
[SerializeField] private Texture2D? itemTexture;
private readonly List<Matrix4x4>[] _matrices = { new(), new(), new(), new(), new(), new() };
private readonly Material[] _materials = new Material[6];
private Mesh? _quad;
private Demo2EcsWorld? _world;
public void Bind(Demo2EcsWorld? world) => _world = world;
public void SetTexture(Texture2D texture) { itemTexture = texture; RebuildMaterials(); }
private void Awake()
{
if (Application.isBatchMode)
{
enabled = false;
return;
}
_quad = CreateQuad();
RebuildMaterials();
}
private void LateUpdate()
{
if (_world == null || _quad == null) return;
for (var i = 0; i < _matrices.Length; i++) _matrices[i].Clear();
var manager = _world.EntityManager;
var query = manager.CreateEntityQuery(typeof(Demo2GridPosition), typeof(Demo2MaterialState));
using var entities = query.ToEntityArray(Allocator.Temp);
using var positions = query.ToComponentDataArray<Demo2GridPosition>(Allocator.Temp);
using var materials = query.ToComponentDataArray<Demo2MaterialState>(Allocator.Temp);
for (var i = 0; i < entities.Length; i++)
{
var material = materials[i];
var x = positions[i].X + 0.5f;
var y = Demo2Protocol.GridHeight - positions[i].Y - 0.5f;
var offset = material.SubCellProgress / 1000f;
switch (material.Direction & 3) { case 0: x += offset; break; case 1: y += offset; break; case 2: x -= offset; break; case 3: y -= offset; break; }
var kind = Mathf.Clamp((int)material.Kind, 0, _matrices.Length - 1);
if (_matrices[kind].Count < 1023) _matrices[kind].Add(Matrix4x4.TRS(new Vector3(x, y, -0.2f), Quaternion.identity, Vector3.one * 0.34f));
}
for (var i = 0; i < _matrices.Length; i++)
if (_materials[i] != null && _matrices[i].Count > 0)
Graphics.DrawMeshInstanced(_quad, 0, _materials[i], _matrices[i]);
}
private void OnDestroy()
{
if (_quad != null) Destroy(_quad);
for (var i = 0; i < _materials.Length; i++) if (_materials[i] != null) Destroy(_materials[i]);
}
private void RebuildMaterials()
{
var colors = new[] { new Color(0.52f, 0.66f, 0.78f), new Color(0.42f, 0.32f, 0.28f), new Color(0.82f, 0.82f, 0.76f), new Color(0.86f, 0.68f, 0.22f), new Color(0.84f, 0.23f, 0.18f), new Color(0.16f, 0.82f, 0.88f) };
var shader = Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Texture");
if (shader == null)
{
enabled = false;
return;
}
for (var i = 0; i < _materials.Length; i++)
{
if (_materials[i] == null) _materials[i] = new Material(shader) { enableInstancing = true };
_materials[i].mainTexture = itemTexture;
_materials[i].color = colors[i];
}
}
private static Mesh CreateQuad()
{
var mesh = new Mesh { name = "Demo2 Item Quad" };
mesh.SetVertices(new[] { new Vector3(-.5f, -.5f), new Vector3(-.5f, .5f), new Vector3(.5f, .5f), new Vector3(.5f, -.5f) });
mesh.SetUVs(0, new[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) });
mesh.SetTriangles(new[] { 0, 1, 2, 0, 2, 3 }, 0);
mesh.RecalculateBounds();
return mesh;
}
}
}