From 5ccab35948d007d4db52de454df10a61655e551e Mon Sep 17 00:00:00 2001 From: Joywayer Date: Fri, 12 Jun 2026 11:26:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(world):=20=E6=A3=80=E6=9F=A5=E7=82=B9?= =?UTF-8?q?=E5=A4=8D=E6=B4=BB=E4=BD=8D=E7=BD=AE=E7=94=B1=20RespawnPoint=20?= =?UTF-8?q?=E5=AD=90=E8=8A=82=E7=82=B9=E6=98=BE=E5=BC=8F=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CheckpointMarker 新增 _respawnPoint 引用,注册的检查点位置改为 该子节点的位置——触发区与出生点解耦,触发区可横跨通道、出生点 精确落在安全平台上。漏配时 Awake 显式报错且不注册(不以标记 自身位置兜底)。Gizmos 增画复活点(青色)与触发区连线,漏配 画红叉警示。PlaceCheckpointMarker 脚手架自动创建并绑定 RespawnPoint 子节点。 Co-Authored-By: Claude Fable 5 --- .../Editor/Scene/SceneObjectPlacerTool.cs | 6 ++++ .../_Game/Scripts/World/CheckpointMarker.cs | 30 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs b/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs index 46dada3..6b16e76 100644 --- a/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs +++ b/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs @@ -1636,8 +1636,14 @@ namespace BaseGames.Editor AssignLayerMask(marker, "_playerLayers", "Player", report); AssignAsset(marker, "_onCheckpointReached", report, false, "EVT_CheckpointReached"); + // RespawnPoint 子节点:玩家回溯时的出生位置(触发区与出生点解耦) + Transform respawnT = GetOrCreateChild(go.transform, "RespawnPoint"); + respawnT.localPosition = Vector3.zero; + AssignReference(marker, "_respawnPoint", respawnT, report); + report.Add("放置于跳跳乐段落的关键节点处;玩家经过后成为该房间最近检查点。"); report.Add("同一房间可放置多个,以最近经过的为准。"); + report.Add("调整 RespawnPoint 子节点位置 = 玩家回溯出生位置(须落在安全平台上)。"); Selection.activeGameObject = go; MarkDirtyAndLog("Checkpoint Marker", go, report); diff --git a/Assets/_Game/Scripts/World/CheckpointMarker.cs b/Assets/_Game/Scripts/World/CheckpointMarker.cs index 7aeb0a1..663aa34 100644 --- a/Assets/_Game/Scripts/World/CheckpointMarker.cs +++ b/Assets/_Game/Scripts/World/CheckpointMarker.cs @@ -13,6 +13,8 @@ namespace BaseGames.World /// - 激活状态仅存于运行时,不持久化,换房间后重置 /// - 闩锁按接触周期:进入时注册并广播一次,离开触发区后重置, /// 同一次接触内不重复结算 + /// - 触发区与出生位置解耦:注册的是 _respawnPoint 子节点的位置, + /// 触发区可横跨通道,出生点精确落在安全平台上 /// [RequireComponent(typeof(Collider2D))] public class CheckpointMarker : MonoBehaviour @@ -21,6 +23,10 @@ namespace BaseGames.World [Tooltip("勾选 Player 层")] [SerializeField] private LayerMask _playerLayers; + [Header("复活点")] + [Tooltip("玩家回溯时出现的位置(必配,脚手架自动创建 RespawnPoint 子节点)")] + [SerializeField] private Transform _respawnPoint; + [Header("事件")] [Tooltip("EVT_CheckpointReached — 激活时广播,供 VFX/SFX 使用")] [SerializeField] private VoidEventChannelSO _onCheckpointReached; @@ -38,15 +44,20 @@ namespace BaseGames.World col.isTrigger = true; Debug.LogWarning($"[CheckpointMarker] {name}: Collider2D.isTrigger 已自动设为 true。", this); } + + if (_respawnPoint == null) + Debug.LogError($"[CheckpointMarker] {name}: _respawnPoint 未绑定,检查点无法注册。" + + "请用脚手架(BaseGames/Scene/Place/Checkpoint Marker)创建,或手动补 RespawnPoint 子节点并绑定。", this); } private void OnTriggerEnter2D(Collider2D other) { if (_isActivated) return; if ((_playerLayers.value & (1 << other.gameObject.layer)) == 0) return; + if (_respawnPoint == null) return; // 漏配已在 Awake 报错,此处不以标记自身位置兜底 _isActivated = true; - ServiceLocator.GetOrDefault()?.RegisterCheckpoint(transform.position); + ServiceLocator.GetOrDefault()?.RegisterCheckpoint(_respawnPoint.position); _onCheckpointReached?.Raise(); } @@ -64,6 +75,23 @@ namespace BaseGames.World Gizmos.DrawWireSphere(transform.position, 0.4f); Gizmos.DrawLine(transform.position + Vector3.down * 0.4f, transform.position + Vector3.up * 0.8f); + + // 复活点:青色小球 + 落点竖线 + 与触发区的连线;漏配画红叉警示 + if (_respawnPoint != null) + { + Gizmos.color = new Color(0f, 0.8f, 1f, 0.9f); + Gizmos.DrawWireSphere(_respawnPoint.position, 0.25f); + Gizmos.DrawLine(_respawnPoint.position + Vector3.down * 0.5f, + _respawnPoint.position + Vector3.up * 0.5f); + Gizmos.color = new Color(0f, 0.8f, 1f, 0.4f); + Gizmos.DrawLine(transform.position, _respawnPoint.position); + } + else + { + Gizmos.color = Color.red; + Gizmos.DrawLine(transform.position + new Vector3(-0.3f, -0.3f), transform.position + new Vector3(0.3f, 0.3f)); + Gizmos.DrawLine(transform.position + new Vector3(-0.3f, 0.3f), transform.position + new Vector3(0.3f, -0.3f)); + } } } }