Show player positions on an overlay
How to render a live minimap-style overlay of tracked players, using
PlayerPositionOverlay (itself a
PlayerTracker, no separate tracker component needed) and
RasterPlayerMarkerRenderer.
Steps
-
Add a
PlayerPositionOverlayto your scene and register it as a construct, so codegen callsTsConstructon it at startup. The renderer needs no registration: neitherPlayerMarkerRenderernorRasterPlayerMarkerRendererusesTsStartor_ts, so drop one into the scene and assign it. -
Subclass
RasterPlayerMarkerRendererto decide what a marker looks like:public class DotMarkerRenderer : RasterPlayerMarkerRenderer{public override void DrawMarker(Color32[] pixelBuffer, int textureWidth, int textureHeight,int pixelX, int pixelY, bool isLocalPlayer, float headingDegrees, string playerId){Color32 color = isLocalPlayer ? Color.green : Color.red;TextureGraphics2D.DrawCircleToBuffer(pixelBuffer, textureWidth, textureHeight, pixelX, pixelY, 4, color);}} -
Wire the output texture of the renderer to a
RawImagein your UI, then configure and start the overlay:public class MinimapController : TsBehaviour{[SerializeField] private PlayerPositionOverlay _overlay;[SerializeField] private DotMarkerRenderer _renderer;[SerializeField] private Transform _mapOrigin;protected override void TsStart(){_renderer.Setup(width: 256, height: 256, worldOrigin: _mapOrigin.position, unitsPerGridX: 4f, unitsPerGridZ: 4f);_overlay.Renderer = _renderer;_overlay.StartOverlay(new string[0]);}} -
Add or remove players while it runs with the tracking methods the overlay inherits,
_overlay.AddTrackedPlayers(playerIds)andRemoveTrackedPlayers(playerIds). The renderer picks up the change on its next tick with no extra wiring.
If only a subset of players should ever appear (not everyone in the instance), start the overlay with that explicit ID list instead of an empty one.
Swapping the drawing style
RasterPlayerMarkerRenderer handles the texture, pixel buffer, and flush timing; only
DrawMarker decides the visuals, so a different look (a triangle that rotates with heading,
say) is a different DrawMarker body, not a different setup:
public override void DrawMarker(Color32[] pixelBuffer, int textureWidth, int textureHeight,
int pixelX, int pixelY, bool isLocalPlayer, float headingDegrees, string playerId)
{
TextureGraphics2D.DrawTriangleToBuffer(pixelBuffer, textureWidth, textureHeight, pixelX, pixelY, 5, 5, headingDegrees, someColor);
}
Skipping the raster renderer
If you're not drawing to a texture at all (driving 3D world-space marker objects instead,
for example), implement PlayerMarkerRenderer
directly instead of its raster subclass. PlayerPositionOverlay only calls the two methods of the
base class.
Why this shape
PlayerPositionOverlay is a pure backend that never draws anything itself. See its
reference page for why presentation is split
out into a pluggable renderer, and what the two independent tick loops (position resolution
vs. blink) cost on their own.