t1k:unity:dots-rendering:perspective-2d-topdown
| Field | Value |
|---|---|
| Module | dots-rendering |
| Version | 2.1.7 |
| Effort | high |
| Tools | — |
Keywords: 2D, DOTS, perspective, top-down
How to invoke
Section titled “How to invoke”/t1k:unity:dots-rendering:perspective-2d-topdownDOTS Perspective: 2D Top-Down
Section titled “DOTS Perspective: 2D Top-Down”When This Skill Triggers
Section titled “When This Skill Triggers”- 2D top-down, orthographic camera, sprite rendering, quad mesh, Y-sorting
- SpriteAnimationSystem, SpriteColor, SpriteSheetUV, DeathFadeSystem
- URP/Unlit cutout, alpha clip, flat rendering
Key Concepts
Section titled “Key Concepts”- Simulation: XZ plane (always). All navigation, physics, AI operate on XZ
- Presentation: Camera looks down -Y axis. Entities are flat quads in XZ plane
- No coordinate remapping — simulation coords = visual coords (unlike side-view)
Camera Setup
Section titled “Camera Setup”- Orthographic, rotation
(90, 0, 0), position(0, height, 0) farClipPlane = CameraHeight + 50f(must exceed camera Y position)- Camera uses Cinemachine 3.x (
CinemachineCamera+CinemachinePositionComposer+CinemachineConfiner2D+CinemachineImpulseListener) - Bridge:
CinemachineCameraBridgeMonoBehaviour readsCameraTargetsingleton → proxyTransform→CinemachineCamera.Follow - Auto-zoom:
CinemachineAutoZoomMonoBehaviour queries alive DOTS entities → XZ AABB →cam.orthographicSize CinemachineConfiner2D:BoxCollider2Dmust be on main scene (not SubScene)- → See
references/camera-2d-topdown-guide.mdandunity-cinemachineskill
Rendering
Section titled “Rendering”- Quad mesh in XZ plane: vertices at y=0, spanning
(-0.5, 0, -0.5)to(0.5, 0, 0.5) - Shader:
Universal Render Pipeline/Unlit— no lighting needed for top-down - Material mode: Opaque + AlphaTest (cutout) — enables SRP Batcher batching
- Team color: White base material + per-entity
SpriteColor [MaterialProperty("_BaseColor")] - Shadows:
ShadowCastingMode.Off,receiveShadows = falseon all quads -> Seereferences/rendering-2d-topdown-guide.md
Navigation
Section titled “Navigation”NavigationAuthoring.EnableGrounding = false— skip DOTSGroundingSystem (no Y physics)RangedAttackAuthoring.ArcHeight = 0+IsFlat = true— flat 2D projectile trajectory- Standard XZ NavMeshSurface on ground plane;
NavMeshObstacle.carving = truefor obstacles MappingExtentmust be proportional to arena size (200x200 arena needs ~50)
Animation
Section titled “Animation”SpriteAnimationAuthoringfor sprite sheet UV animation (FrameCount, Columns, FPS)SpriteAnimationSystemadvances frames viaSpriteSheetUV [MaterialProperty("_BaseMap_ST")]DeathFadeSystemlerpsSpriteColor.Value.w(alpha) based onDeathAnimation.Remaining- Static sprites: set
FrameCount = 1,FPS = 0
Common Patterns
Section titled “Common Patterns”Quad Mesh Creation (XZ Plane)
Section titled “Quad Mesh Creation (XZ Plane)”mesh.vertices = new[] { new Vector3(-0.5f, 0f, -0.5f), new Vector3(0.5f, 0f, -0.5f), new Vector3(-0.5f, 0f, 0.5f), new Vector3(0.5f, 0f, 0.5f),};mesh.triangles = new[] { 0, 2, 1, 2, 3, 1 };mesh.normals = new[] { Vector3.up, Vector3.up, Vector3.up, Vector3.up };Cutout Material Setup
Section titled “Cutout Material Setup”mat.SetFloat("_Surface", 0f); // Opaquemat.SetFloat("_AlphaClip", 1f); // Enable cutoutmat.SetFloat("_Cutoff", 0.5f);mat.SetOverrideTag("RenderType", "TransparentCutout");mat.renderQueue = (int)RenderQueue.AlphaTest;mat.EnableKeyword("_ALPHATEST_ON");mat.enableInstancing = true;Gotchas
Section titled “Gotchas”| # | Issue | Fix |
|---|---|---|
| 1 | Camera farClipPlane < CameraHeight = invisible troops | Set farClipPlane = CameraHeight + 50f |
| 2 | Transparent materials defeat SRP Batcher (608 batches) | Use Opaque + AlphaTest cutout (28 batches) |
| 3 | DetectionRadius < spawn gap = troops stand idle | Set DetectionRadius > half the spawn gap distance |
| 4 | Prefab regeneration wipes BDP trees | Always run “Build Behavior Trees” after “Create Unit Prefabs” |
| 5 | while not if for SpriteAnimation frame advance | Large deltaTime can skip multiple frames |
| 6 | CinemachineConfiner2D references SubScene collider | BoxCollider2D for confiner MUST be in main scene |
| 7 | Camera shake saturates with 500+ units | Hundreds of hits/frame × 0.03 trauma = instant max. Remove CinemachineImpulseListener from camera or set CameraTrauma.MaxIntensity=0 |
Cross-References
Section titled “Cross-References”dots-ecs— ECS fundamentalsdots-rpg— SpriteAnimation, SpriteColor, SpriteSheetUV componentsdots-graphics— Rendering fundamentals, MaterialProperty overridesagents-navigation— Pathfinding, NavMesh setupdots-performance— Batching, draw call optimizationunity-cinemachine— CinemachineCameraBridge, Confiner2D, impulse patterns
Reference Files
Section titled “Reference Files”| File | Coverage |
|---|---|
references/rendering-2d-topdown-guide.md | Sprite setup, materials, quad mesh, cutout vs transparent |
references/camera-2d-topdown-guide.md | Orthographic setup, auto-zoom, bounds tracking |