Hello @just_some_game_dev, thank you for your question!
I can't say this is the absolute best solution for your use case, but have you looked into LowLevelMesh? The basic idea is that you can create a single mesh with detached quads that sit above your enemies. Each quad has UVs calculated so that its material reads from one texture (an atlas) that contains every digit, 0 through 9. See Creating a plane with low-level mesh and Generating interactive geometry with RealityKit for more details about how to build custom meshes at runtime.
A few details that help:
- Put positions and UVs in separate vertex buffers. UVs are only written once when a number appears, then each frame you only rewrite positions.
- Give the mesh a fixed capacity and update its
parts so only the live quads are drawn. - Use a transparent unlit material with depth writes turned off, so overlapping digits don't hide each other.
To have the quads of your LowLevelMesh face the camera, update the positions of the vertices directly in a system, building each quad's corners from the camera's right and up directions. Note that BillboardComponent rotates the whole entity, so it doesn't apply here, because every damage number is part of a single mesh.
MeshInstancesComponent was another option I considered, as it can draw the same mesh many times in one draw call. However, the only thing you can vary per instance is the transform, so you'd need a separate instanced quad for each digit and one instance per digit of each number. LowLevelMesh is more direct.
When it comes to custom Metal shaders, the solution above doesn't require any, because the atlas lookup on the digits texture is done by the vertex data. It may be possible to optimize this further by moving the vertex writing to a compute kernel that runs on the GPU, but I highly recommend starting with a Swift version and only attempting GPU optimizations once you are confident your Swift system has become a bottleneck.
If you'd like this to be more built-in and straightforward, please send us a feature request using Feedback Assistant, describing your use case. See Bug Reporting: How and Why? for tips on creating tickets. If you post the ticket number here, I can make sure it gets seen by the right people.
Thank you!