Vixen
dd8b0a81
csharp
public sealed class TerrainColliderSystem

Gives every terrain in the world a collider: one height-field shape per tile.

Read the guide page for this →

As a system

Phase
EarlyUpdate

Remarks

[31 § D10](../../docs/plan/31-terrain-grass-and-trees.md#d10-collision-is-the-heightfield-and-trees-are-collided-within-a-radius), and the call that was missing. Every piece of this path was built and tested and nothing joined them: PhysicsShapes.HeightField registers the Jolt shape, TerrainSamples.FillCollisionSamples produces exactly the span it consumes — metres, row-major, holes as the caller's sentinel — and ITerrainPlacements says where the ground is. So a terrain in a game had no collision at all, in any project, and the symptom was not an error: a character walked onto it and fell through.

⚠ The tile is the unit, and that is [§ D2] rather than an optimisation. One tile is one shape, so a stroke that dirties one tile out of sixteen rebuilds one — and a terrain whose collision was one shape would pause for the whole terrain every time somebody smoothed a ridge.

⚠ Tiles share their boundary samples, so the shapes overlap by one quad. That is the terrain's own arithmetic — TileQuads is TileSamples − 1 — and it is right: a gap of one quad between two height fields is a seam a character falls through, and an overlap is two surfaces at identical heights, which Jolt resolves as one.

⚠ It asks every frame rather than building once, and that is the whole reason it is a system. A .vxterrain is tens of megabytes: ITerrainAssetSource starts a load and answers null for several frames, so a one-shot call at level load gets nothing and builds nothing, silently. Once a terrain has bodies the per-frame cost is one integer compare per tile.

⚠ A tile is rebuilt when its composite changes, without anybody having to say so. RevisionOf counts recomposites, so a stroke that ran through Resolve moves the collider on the next frame. ITerrainColliders — the editor's seam — is the synchronous form of the same job for a tool that cannot wait a frame; Rebuild is what such an adapter calls.

⚠ Holes are watched by count, which is coarse and is the honest bound. TerrainHoles carries no per-tile version and punching one moves no height, so the poll cannot see which tile changed and rebuilds that terrain's tiles when HoleCount moves. A tool that punches and fills within one frame nets zero and is missed; that tool should call Rebuild, which is precise.

⚠ In EarlyUpdate, so the bodies exist before the step. PhysicsSyncSystem creates a Jolt body for every entity with a Collider and a LocalTransform and no RigidBody beside it, which is how a static body is spelled — a height field cannot be dynamic and ShapeDescription.CanBeDynamic says so, so anything else would throw.

Fields and properties (6)

  • public ITerrainPlacements? Placements

    Where the terrains are, or null to build nothing.

  • public float Friction

    The friction every tile's collider is given.

  • public int TerrainCount

    How many terrains have colliders.

  • public int TileCount

    How many tile bodies exist across all of them.

  • public int Rebuilds

    How many tiles have been rebuilt since the world started, after their first build.

  • public SystemAccess Access

Methods (6)

  • public TerrainColliderSystem(PhysicsScene scene, ITerrainPlacements placements)

    Gives every terrain in the world a collider: one height-field shape per tile.

  • public override JobHandle Update(in SystemContext context, JobHandle dependency)

    Runs the system.

  • public void Sync()

    Brings the colliders into step with the placements, once.

  • public bool Rebuild(Terrain terrain, int tileX, int tileZ)

    Rebuilds one tile's collision shape now.

  • public bool Rebuild(Terrain terrain, TerrainRect rect)

    Rebuilds every tile a rectangle of samples touches.

  • public bool Forget(Terrain terrain)

    Destroys a terrain's collision bodies.

Used by (5)

  • ArenaThirdPersonShooter
  • TerrainColliderSystemTestsVixen.Terrain.Physics.Tests
  • PlayTerrainCollidersVixen.Editor.Terrain.Physics
  • SculptedGroundTestsVixen.Editor.Terrain.Physics.Tests
  • TerrainCollidersVixen.Editor.Terrain.Physics