t1k:unity:dots-rendering:perspective-2d-sideview
| Field | Value |
|---|---|
| Module | dots-rendering |
| Version | 2.1.7 |
| Effort | high |
| Tools | — |
Keywords: 2D, DOTS, perspective, side-view
How to invoke
Section titled “How to invoke”/t1k:unity:dots-rendering:perspective-2d-sideviewDOTS Perspective: 2D Side-View
Section titled “DOTS Perspective: 2D Side-View”When This Skill Triggers
Section titled “When This Skill Triggers”- Side-view, side-scrolling, 2.5D, Z-to-Y remap, parallax
- SideViewTransformSystem, SideViewRestoreSystem, SideViewConfig, SideViewGameZ
- Camera facing -Z, orthographic
Key Concepts
Section titled “Key Concepts”- Simulation: XZ plane (always). NavMesh, physics, AI all operate on XZ
- Presentation: Camera looks along -Z. Visual Y = f(simulation Z). X is shared
- CRITICAL: Visual transform must NEVER feed back to simulation. Save/restore is mandatory
Camera Setup
Section titled “Camera Setup”- Orthographic, position
(0, 0, -100), rotationidentity(facing +Z) - Pan X only (tracks battle center X). Y and Z are fixed
transparencySortAxis = (0, 0, 1)— higher Z renders behind lower Z- Auto-zoom via X extents:
targetSize = (extentX + Padding) / aspect-> Seereferences/sideview-navigation-guide.md
Rendering
Section titled “Rendering”- Same quad mesh + URP/Unlit cutout as 2D top-down (shared Quad2D asset)
- Quads face -Z (toward camera) — use Unity default Quad primitive or custom mesh
- Parallax backdrop: multiple layers at different Z depths with UV scrolling
- Backdrop materials: transparent (not cutout) since they are static background, not DOTS entities
-> See
references/sideview-transform-guide.md
The Save/Restore Pattern (MANDATORY)
Section titled “The Save/Restore Pattern (MANDATORY)”This is the most critical pattern for side-view. Without it, Z collapses exponentially.
System Pair
Section titled “System Pair”-
SideViewRestoreSystem —
SimulationSystemGroup, OrderFirst = true- Restores canonical Z from
SideViewGameZ.Valuebefore any simulation - Resets Y to 0 (simulation ground plane)
- Adds
SideViewGameZto newly spawned entities via ECB
- Restores canonical Z from
-
SideViewTransformSystem —
PresentationSystemGroup- Saves canonical Z into
SideViewGameZ.Value - Maps:
Y = BaseY + Z * DepthScale - Spreads Z:
Z *= DepthSpread(prevents depth-buffer fighting)
- Saves canonical Z into
Data Flow Per Frame
Section titled “Data Flow Per Frame”Frame start → RestoreSystem (Z = saved, Y = 0) → Navigation/Physics/AI (operate on canonical XZ) → All simulation systemsFrame end → TransformSystem (save Z, remap Y, spread Z) → Rendering sees visual positionsNavigation
Section titled “Navigation”- XZ NavMesh on invisible ground plane (MeshRenderer disabled)
- Obstacles are invisible cubes with
NavMeshObstacle.carving = true - Same
NavigationAuthoring.EnableGrounding = falseas 2D top-down RangedAttackAuthoring.ArcHeight = 0,IsFlat = true-> Seereferences/sideview-navigation-guide.md
Animation
Section titled “Animation”- Same
SpriteAnimationAuthoringstack as 2D top-down - Side-profile character sprites (facing left/right)
DeathFadeSystemworks identically
SideViewConfig Singleton
Section titled “SideViewConfig Singleton”public struct SideViewConfig : IComponentData { public float DepthScale; // Z→Y multiplier (0.3 = Z10 → Y3) public float BaseY; // Ground line Y offset public float DepthSpread; // Z spread to prevent Z-fighting (0.1)}Add via SideViewAuthoring MonoBehaviour in SubScene.
Parallax Backdrop
Section titled “Parallax Backdrop”// Camera controller with parallax layerspublic struct ParallaxLayer { public Renderer Quad; public float Factor; // 0.0 = static, 1.0 = full scroll}// On camera move: mat.mainTextureOffset.x += dx * Factor * 0.1fLayers at increasing Z: Sky (50), Mountains (40), Trees (30), Ground (10).
Gotchas
Section titled “Gotchas”| # | Issue | Fix |
|---|---|---|
| 1 | Z-position feedback loop — Z *= 0.1 each frame → collapse to 0 | SideViewRestoreSystem must run OrderFirst in SimulationSystemGroup |
| 2 | Projectiles/AoE invisible — missing SideViewGameZ | RestoreSystem adds SideViewGameZ to ALL entities with LocalTransform, not just GameEntityTag |
| 3 | Depth-buffer Z-fighting between overlapping quads | DepthSpread multiplier separates Z positions for depth buffer |
| 4 | NavMesh ground visible as edge-on plane | Set MeshRenderer.enabled = false on ground |
| 5 | Obstacles visible in side-view | Set MeshRenderer.enabled = false on obstacle cubes |
Cross-References
Section titled “Cross-References”dots-ecs— ECS fundamentalsdots-rpg— SideViewConfig, SideViewGameZ, SpriteAnimation componentsdots-perspective-2d-topdown— Shared rendering patterns (cutout materials, quad mesh)agents-navigation— Pathfinding on XZ planedots-graphics— MaterialProperty overrides
Reference Files
Section titled “Reference Files”| File | Coverage |
|---|---|
references/sideview-transform-guide.md | Save/restore pattern, config, Z-fighting, system ordering |
references/sideview-navigation-guide.md | XZ NavMesh with XY display, invisible ground, camera setup |