2025-10-15 21:31:13 +08:00
|
|
|
|
using UnityEngine;
|
2025-10-20 09:02:15 +08:00
|
|
|
|
using Script.Gameplay.Interface;
|
2025-10-15 21:31:13 +08:00
|
|
|
|
using System;
|
2025-10-17 15:10:19 +08:00
|
|
|
|
using Script.Gameplay.Input;
|
2025-10-15 21:31:13 +08:00
|
|
|
|
|
2025-10-20 10:12:07 +08:00
|
|
|
|
namespace Script.Gameplay.Player
|
2025-10-15 21:31:13 +08:00
|
|
|
|
{
|
|
|
|
|
public class PlayerInteractorController : MonoBehaviour
|
|
|
|
|
{
|
2025-10-18 17:14:09 +08:00
|
|
|
|
[SerializeField] private FirstPersonRaycaster raycaster; // 新增:第一人称射线检测器
|
2025-10-18 11:00:06 +08:00
|
|
|
|
[SerializeField] private bool isEnablePlayerInteraction = true; // 是否启用玩家交互功能
|
2025-10-15 21:31:13 +08:00
|
|
|
|
|
2025-10-17 15:10:19 +08:00
|
|
|
|
private IInteractable currentTarget; // 被射线命中的当前可交互对象(用于按键交互)
|
|
|
|
|
private IInteractable previousGazedTarget; // 上一次注视的对象(用于注视进入/离开事件)
|
2025-10-15 21:31:13 +08:00
|
|
|
|
|
|
|
|
|
void Start()
|
|
|
|
|
{
|
2025-10-18 17:14:09 +08:00
|
|
|
|
if (raycaster == null)
|
|
|
|
|
raycaster = GetComponent<FirstPersonRaycaster>() ?? GetComponentInChildren<FirstPersonRaycaster>();
|
|
|
|
|
if (raycaster == null)
|
|
|
|
|
raycaster = FindObjectOfType<FirstPersonRaycaster>();
|
|
|
|
|
if (raycaster == null)
|
|
|
|
|
Debug.LogWarning("FirstPersonRaycaster not found! Please assign or add it to the player.");
|
2025-10-17 15:10:19 +08:00
|
|
|
|
|
|
|
|
|
var input = InputManager.Instance.Input;
|
2025-10-18 08:55:38 +08:00
|
|
|
|
input.Player.Interact.performed += ctx =>
|
|
|
|
|
{
|
|
|
|
|
if (currentTarget != null)
|
|
|
|
|
{
|
|
|
|
|
currentTarget.Interact(this.gameObject);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-10-15 21:31:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Update()
|
|
|
|
|
{
|
|
|
|
|
DetectInteractable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DetectInteractable()
|
|
|
|
|
{
|
2025-10-18 17:14:09 +08:00
|
|
|
|
if (raycaster == null) return;
|
2025-10-18 11:00:06 +08:00
|
|
|
|
if (!isEnablePlayerInteraction) return;
|
2025-10-17 15:10:19 +08:00
|
|
|
|
|
2025-10-18 17:14:09 +08:00
|
|
|
|
GameObject lookAtObj = raycaster.CurrentLookAtObject;
|
|
|
|
|
IInteractable hitInteractable = lookAtObj != null ? lookAtObj.GetComponent<IInteractable>() : null;
|
2025-10-17 15:10:19 +08:00
|
|
|
|
|
2025-10-18 17:14:09 +08:00
|
|
|
|
// 如果命中对象与之前注视的不一样,触发进入/离开事件
|
|
|
|
|
if (hitInteractable != previousGazedTarget)
|
2025-10-15 21:31:13 +08:00
|
|
|
|
{
|
2025-10-17 15:10:19 +08:00
|
|
|
|
if (previousGazedTarget != null)
|
|
|
|
|
{
|
|
|
|
|
previousGazedTarget.OnGazeExit(this.gameObject);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-18 17:14:09 +08:00
|
|
|
|
if (hitInteractable != null)
|
|
|
|
|
{
|
|
|
|
|
hitInteractable.OnGazeEnter(this.gameObject);
|
|
|
|
|
// 这里可以显示交互提示UI,例如 “E - 开门”
|
|
|
|
|
Debug.Log(hitInteractable.GetInteractPrompt());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
previousGazedTarget = hitInteractable;
|
2025-10-15 21:31:13 +08:00
|
|
|
|
}
|
2025-10-18 17:14:09 +08:00
|
|
|
|
|
|
|
|
|
currentTarget = hitInteractable;
|
2025-10-15 21:31:13 +08:00
|
|
|
|
}
|
2025-10-18 11:00:06 +08:00
|
|
|
|
|
|
|
|
|
public void SetPlayerInteractionEnabled(bool isEnabled)
|
|
|
|
|
{
|
|
|
|
|
isEnablePlayerInteraction = isEnabled;
|
|
|
|
|
if (!isEnabled && previousGazedTarget != null)
|
|
|
|
|
{
|
|
|
|
|
previousGazedTarget.OnGazeExit(this.gameObject);
|
|
|
|
|
previousGazedTarget = null;
|
|
|
|
|
currentTarget = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-17 15:10:19 +08:00
|
|
|
|
|
2025-10-15 21:31:13 +08:00
|
|
|
|
void OnDrawGizmos()
|
|
|
|
|
{
|
2025-10-18 17:14:09 +08:00
|
|
|
|
// 交由 FirstPersonRaycaster 绘制射线
|
2025-10-15 21:31:13 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|