DR-042 Phase C (legibility, part 2): walls block enemies (C5) — restore the fortress fantasy

Player-built structures now physically block enemies (husks walked straight through walls before). Dedicated
"Structure" physics layer (slot 9) so the player passes its own walls while enemies are stopped:

- New WorldCollisionConfig.StructureMask, baked from the "Structure" layer in WorldCollisionAuthoring (mirrors
  EnvironmentMask). EnemyAISystem ORs it into the movement sweep filter (CollidesWith = envMask | structMask) —
  no new system, same 1-2 SphereCasts per enemy.
- Wall/Turret/Pylon prefabs get a cell-sized BoxCollider on the Structure layer (Wall's existing one relayered).
- Physics matrix: Default x Structure unchecked, so the kinematic player CC (Default) passes its own walls while
  the enemy's explicit cast still hits them. Despawn frees collision for free (collider dies with the entity).

Play-verified baked filters: StructMask=512; structure colliders BelongsTo=512, CollidesWith=0xFFFFFFFE
(includes Environment for the enemy cast, EXCLUDES bit 0 so the player passes). 389/389 EditMode, no exceptions.
Server-only/static colliders -> deterministic, no client divergence. SaveData stays v5.

Phase C complete (C5-C7). A visual fun-gate (husk stops at wall, player walks through) is the operator's eyes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-25 21:26:56 -07:00
parent 419debad74
commit bd8458853b
8 changed files with 78 additions and 12 deletions
+23 -1
View File
@@ -102,7 +102,8 @@ GameObject:
- component: {fileID: 9053853372340598254}
- component: {fileID: 6834786618115927220}
- component: {fileID: 7685488391646220227}
m_Layer: 0
- component: {fileID: 1225369404710843925}
m_Layer: 9
m_Name: Pylon
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -177,3 +178,24 @@ MonoBehaviour:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.StructureAuthoring
Kind: 6
MaxHp: 150
--- !u!65 &1225369404710843925
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1.6, y: 2, z: 1.6}
m_Center: {x: 0, y: 1, z: 0}
+23 -1
View File
@@ -378,7 +378,8 @@ GameObject:
- component: {fileID: 9053853372340598254}
- component: {fileID: 6834786618115927220}
- component: {fileID: 1794795016809289889}
m_Layer: 0
- component: {fileID: 9049467567705961987}
m_Layer: 9
m_Name: Turret
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -455,6 +456,27 @@ MonoBehaviour:
CooldownTicks: 30
Damage: 12
MaxHp: 120
--- !u!65 &9049467567705961987
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1.6, y: 2, z: 1.6}
m_Center: {x: 0, y: 1, z: 0}
--- !u!1 &4051895978514069616
GameObject:
m_ObjectHideFlags: 0
+1 -1
View File
@@ -103,7 +103,7 @@ GameObject:
- component: {fileID: 6834786618115927220}
- component: {fileID: 8793146551006314905}
- component: {fileID: 7779358222264100756}
m_Layer: 0
m_Layer: 9
m_Name: Wall
m_TagString: Untagged
m_Icon: {fileID: 0}