Refactor interaction prompt system to use world space prompts
- Removed the InteractPromptWidget from HUD and its references in HUDController. - Introduced IInteractPromptView interface for world space interaction prompts. - Implemented WorldInteractPrompt class to manage display of interaction prompts in world space. - Updated InteractableDetector to handle showing/hiding of world space prompts based on player proximity to interactable objects. - Created a new prefab for UI_WorldInteractPrompt to facilitate the new interaction prompt system.
This commit is contained in:
@@ -22,7 +22,7 @@ namespace BaseGames.Editor.Input
|
||||
/// ① 当前 Action × 当前设备的绑定路径 + Sprite 字段
|
||||
/// ② 48px 大图预览
|
||||
/// ③ 所有设备快览行(4 行)
|
||||
/// ④ 模拟 InteractPromptWidget 外观预览
|
||||
/// ④ 模拟交互提示 外观预览
|
||||
///
|
||||
/// 菜单:BaseGames / Input Icon Studio (priority=55)
|
||||
/// </summary>
|
||||
@@ -621,7 +621,7 @@ namespace BaseGames.Editor.Input
|
||||
var effectivePath = GetEffectivePath(_selectedAction);
|
||||
var sprite = (iconSet != null && effectivePath != null) ? iconSet.GetIcon(effectivePath) : null;
|
||||
|
||||
// 模拟 InteractPromptWidget 的外观
|
||||
// 模拟交互提示 的外观
|
||||
var mockup = new VisualElement();
|
||||
mockup.style.flexDirection = FlexDirection.Row;
|
||||
mockup.style.alignItems = Align.Center;
|
||||
|
||||
@@ -224,6 +224,14 @@ namespace BaseGames.Editor
|
||||
if (equipmentConfig != null) AssignReference(equipmentManager, "_config", equipmentConfig, report);
|
||||
if (charmCatalog != null) AssignReference(equipmentManager, "_charmCatalog", charmCatalog, report);
|
||||
|
||||
// ── 交互探测器(检测最近可交互物 + 交互键调用 IInteractable.Interact + 驱动其世界空间提示)──
|
||||
// 扫描 TriggerZone 层上的可交互物(门/存档点/商店/传送点…)。
|
||||
// 提示表现由各交互物自带的世界空间子节点(WorldInteractPrompt)负责,本组件不持有 UI。
|
||||
InteractableDetector interactDetector = GetOrAddComponent<InteractableDetector>(root);
|
||||
AssignLayerMask(interactDetector, "_interactableLayer", new[] { "TriggerZone" }, report);
|
||||
if (inputReader != null)
|
||||
AssignReference(interactDetector, "_inputReader", inputReader, report);
|
||||
|
||||
if (animConfig == null) report.Add("★ 需创建并绑定:PlayerController._animConfig(PLY_PlayerAnimationConfig)");
|
||||
if (statsConfig == null) report.Add("★ 需创建并绑定:PlayerStats._config(PlayerStatsSO)");
|
||||
if (inputReader == null) report.Add("★ 需手动绑定:PlayerController._inputReader / FormController._input / SkillManager._input(InputReaderSO)");
|
||||
@@ -1687,6 +1695,9 @@ namespace BaseGames.Editor
|
||||
AssignAsset(savePoint, "_onSceneLoaded", report, false, "EVT_SceneLoaded");
|
||||
AssignAsset(savePoint, "_onSavePointActivated", report, false, "EVT_SavePointActivated");
|
||||
|
||||
// 世界空间交互提示
|
||||
AttachInteractPrompt(go, 1.3f, report);
|
||||
|
||||
report.Add("已自动生成唯一 _savePointId(可按需改为语义化 ID,如 SP_Forest_Entrance)。");
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
@@ -1747,6 +1758,30 @@ namespace BaseGames.Editor
|
||||
MarkDirtyAndLog("Room Transition", go, report);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在交互物上挂载世界空间交互提示(UI_WorldInteractPrompt 预制体),作为子节点跟随物体显示。
|
||||
/// 提示显隐由玩家身上的 InteractableDetector 在进入/离开最近可交互物时驱动(按 IInteractPromptView 接口)。
|
||||
/// 幂等:已存在同名子节点则跳过。localY 为气泡相对物体的高度,可后续在场景中拖动该子节点单独微调。
|
||||
/// </summary>
|
||||
private static void AttachInteractPrompt(GameObject host, float localY, List<string> report)
|
||||
{
|
||||
if (host.transform.Find("InteractPrompt") != null) return;
|
||||
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(
|
||||
"Assets/_Game/Prefabs/UI/UI_WorldInteractPrompt.prefab");
|
||||
if (prefab == null)
|
||||
{
|
||||
report.Add("★ 未找到 UI_WorldInteractPrompt 预制体,已跳过交互提示挂载(检查 Assets/_Game/Prefabs/UI/)。");
|
||||
return;
|
||||
}
|
||||
|
||||
var go = (GameObject)PrefabUtility.InstantiatePrefab(prefab, host.transform);
|
||||
go.name = "InteractPrompt";
|
||||
go.transform.localPosition = new Vector3(0f, localY, 0f);
|
||||
Undo.RegisterCreatedObjectUndo(go, "Attach InteractPrompt");
|
||||
report.Add("已挂载世界空间交互提示(InteractPrompt 子节点)。拖动它可单独微调气泡位置/样式。");
|
||||
}
|
||||
|
||||
[MenuItem("BaseGames/Scene/Place/Door Transition", priority = 141)]
|
||||
public static void PlaceDoorTransition()
|
||||
{
|
||||
@@ -1774,6 +1809,9 @@ namespace BaseGames.Editor
|
||||
AssignBool(door, "_autoTrigger", false); // 默认需玩家按交互键
|
||||
AssignReference(door, "_animancer", animancer, report);
|
||||
|
||||
// 世界空间交互提示(按交互键模式默认显示)
|
||||
AttachInteractPrompt(go, 1.6f, report);
|
||||
|
||||
AssignAsset(door, "_onSceneLoadRequest", report, false, "EVT_SceneLoadRequest");
|
||||
|
||||
report.Add("填写 _targetSceneAddress(目标场景 Addressable Key)与 _targetTransitionId(目标 PlayerSpawnPoint 的 _transitionId)。");
|
||||
@@ -1843,6 +1881,10 @@ namespace BaseGames.Editor
|
||||
AssignReference(doorA, "_linkedDoor", doorB, report);
|
||||
AssignReference(doorB, "_linkedDoor", doorA, report);
|
||||
|
||||
// 世界空间交互提示(仅在该门切到按交互键模式 _autoTrigger=false 时才会显示)
|
||||
AttachInteractPrompt(goA, 1.6f, report);
|
||||
AttachInteractPrompt(goB, 1.6f, report);
|
||||
|
||||
report.Add("LinkedDoor_A ↔ LinkedDoor_B 已互相绑定,统一挂在 LinkedDoorPair 父节点下。");
|
||||
report.Add("将两扇门移到场景中正确位置后,拖动各自的子节点 SpawnPoint 调整玩家传送到达位置。");
|
||||
report.Add("转场效果:在各门 GameObject 上添加 SceneFeedback 组件并绑定 MMF_Player(如淡入淡出),再将其拖入 _transitionOut(淡出)和 _transitionIn(淡入)字段。");
|
||||
|
||||
@@ -87,21 +87,8 @@ namespace BaseGames.Editor.UI
|
||||
le.preferredHeight = 40f;
|
||||
}
|
||||
|
||||
// ── 交互提示(InteractPrompt)─────────────────────────────────────
|
||||
GameObject interactPromptGo = GetOrCreateChild(hudRootGo.transform, "InteractPrompt").gameObject;
|
||||
InteractPromptWidget interactWidget = GetOrAddComponent<InteractPromptWidget>(interactPromptGo);
|
||||
|
||||
GameObject promptRootGo = GetOrCreateChild(interactPromptGo.transform, "Root").gameObject;
|
||||
GameObject promptKeyIconGo = GetOrCreateChild(promptRootGo.transform, "KeyIcon").gameObject;
|
||||
Image keyIcon = GetOrAddComponent<Image>(promptKeyIconGo);
|
||||
GameObject promptLabelGo = GetOrCreateChild(promptRootGo.transform, "LabelText").gameObject;
|
||||
TMP_Text promptLabel = GetOrAddComponent<TextMeshProUGUI>(promptLabelGo);
|
||||
promptLabel.text = "互动";
|
||||
promptRootGo.SetActive(false);
|
||||
|
||||
AssignRef(interactWidget, "_keyIcon", keyIcon);
|
||||
AssignRef(interactWidget, "_labelText", promptLabel);
|
||||
AssignRef(interactWidget, "_root", promptRootGo);
|
||||
// 交互提示已改为「每个交互物自带的世界空间提示」(WorldInteractPrompt),
|
||||
// 不再放在屏幕固定 HUD 上。由交互物脚手架在各自预制体/场景物体上创建。
|
||||
|
||||
// ── 法术槽(SpellSlot)───────────────────────────────────────────
|
||||
GameObject spellSlotGo = GetOrCreateChild(hudRootGo.transform, "SpellSlot").gameObject;
|
||||
@@ -209,7 +196,6 @@ namespace BaseGames.Editor.UI
|
||||
AssignRef(hudCtrl, "_spiritGaugeFill", spiritFill);
|
||||
AssignRef(hudCtrl, "_lingZhuText", lingZhuText);
|
||||
AssignRef(hudCtrl, "_springContainer", springContainerGo.transform);
|
||||
AssignRef(hudCtrl, "_interactPromptWidget", interactWidget);
|
||||
AssignArrayRefs(hudCtrl, "_formIcons", formImages, report);
|
||||
|
||||
// ── HP 格子 / 回春图标 Prefab(自动创建并绑定,无需手工补)──────────
|
||||
@@ -229,9 +215,6 @@ namespace BaseGames.Editor.UI
|
||||
AssignAsset(hudCtrl, "_onSpringChargesChanged", report, false, "EVT_SpringChargesChanged", "EVT_SpringCharges");
|
||||
AssignAsset(hudCtrl, "_onFormChanged", report, false, "EVT_FormChanged");
|
||||
|
||||
AssignAsset(interactWidget, "_onShowPrompt", report, false, "EVT_ShowInteractPrompt", "EVT_InteractPromptShow");
|
||||
AssignAsset(interactWidget, "_onHidePrompt", report, false, "EVT_HideInteractPrompt", "EVT_InteractPromptHide");
|
||||
|
||||
AssignAsset(bossHPBar, "_onBossFightToggled", report, false, "EVT_BossFightToggled", "EVT_BossFightStarted");
|
||||
AssignAsset(bossHPBar, "_onBossHPChanged", report, false, "EVT_BossHPChanged");
|
||||
AssignAsset(bossHPBar, "_onBossHPMaxSet", report, false, "EVT_BossHPMaxSet");
|
||||
@@ -266,8 +249,6 @@ namespace BaseGames.Editor.UI
|
||||
// 右下角:法术槽 + 工具栏
|
||||
SetRect(spellSlotGo.transform, BottomRight, BottomRight, new Vector2(-40f, 40f), new Vector2(90f, 90f));
|
||||
SetRect(toolHUDGo.transform, BottomRight, BottomRight, new Vector2(-150f, 40f), new Vector2(180f, 90f));
|
||||
// 底部居中:交互提示
|
||||
SetRect(interactPromptGo.transform, BottomCenter, BottomCenter, new Vector2(0f, 140f), new Vector2(320f, 64f));
|
||||
|
||||
// ── 手工步骤说明 ──────────────────────────────────────────────────
|
||||
// _hpCellPrefab / _springIconPrefab 已自动创建并绑定(占位红/青方块,美术可替换)。
|
||||
|
||||
Reference in New Issue
Block a user