112 lines
3.6 KiB
C#
112 lines
3.6 KiB
C#
using UnityEngine;
|
|
using DG.Tweening; // 引入 DOTween 命名空间
|
|
|
|
namespace Interaction
|
|
{
|
|
public class DoorController : MonoBehaviour, IInteractable
|
|
{
|
|
[System.Serializable]
|
|
public class DoorLeaf
|
|
{
|
|
[Tooltip("门页对象")]
|
|
public Transform doorTransform;
|
|
|
|
[Tooltip("开门时,该门页的 Y 轴角度 (例如 90 或 -90)")]
|
|
public float openAngle = 90f;
|
|
}
|
|
|
|
[Header("门页设置")]
|
|
[Tooltip("请绑定门页对象 (最多两个),并设置各自的开门角度。关门角度默认为 0 度。")]
|
|
[SerializeField] private DoorLeaf[] doorLeaves;
|
|
|
|
[Header("动画设置")]
|
|
[Tooltip("开门需要几秒钟")]
|
|
[SerializeField] private float duration = 1.0f;
|
|
[SerializeField] private Ease animationEase = Ease.OutQuad;
|
|
|
|
// 运行时状态
|
|
private bool isOpen = false; //默认关闭
|
|
|
|
public bool IsOpen => isOpen;
|
|
|
|
private void Start()
|
|
{
|
|
// 校验配置
|
|
if (doorLeaves == null || doorLeaves.Length == 0)
|
|
{
|
|
Debug.LogWarning("[DoorController] 未绑定任何门页 (Door Leaves)!请在 Inspector 中设置。");
|
|
return;
|
|
}
|
|
|
|
// 初始化状态判断:
|
|
// 我们以"第一个门页"的状态为准来判断当前整个门是开还是关
|
|
var firstLeaf = doorLeaves[0];
|
|
if (firstLeaf.doorTransform == null) return;
|
|
|
|
float currentY = firstLeaf.doorTransform.localEulerAngles.y;
|
|
|
|
// 处理欧拉角 360 度问题 (比如 -90 度可能是 270)
|
|
if (currentY > 180) currentY -= 360;
|
|
|
|
// 关门角度默认为 0
|
|
float distToClose = Mathf.Abs(Mathf.DeltaAngle(currentY, 0f));
|
|
float distToOpen = Mathf.Abs(Mathf.DeltaAngle(currentY, firstLeaf.openAngle));
|
|
|
|
isOpen = distToOpen < distToClose;
|
|
|
|
Debug.Log($"[Door] 初始化完成。当前角度: {currentY}, 判定为: {(isOpen ? "开" : "关")}");
|
|
}
|
|
|
|
public void Interact()
|
|
{
|
|
if (doorLeaves == null || doorLeaves.Length == 0) return;
|
|
|
|
Debug.Log($"<color=green>[Door] 收到交互请求!当前状态 isOpen: {isOpen}</color>");
|
|
ToggleDoor();
|
|
}
|
|
|
|
public string GetInteractPrompt()
|
|
{
|
|
return isOpen ? "关闭" : "打开";
|
|
}
|
|
|
|
public void OpenDoor()
|
|
{
|
|
if (isOpen) return;
|
|
ToggleDoor();
|
|
}
|
|
|
|
public void CloseDoor()
|
|
{
|
|
if (!isOpen) return;
|
|
ToggleDoor();
|
|
}
|
|
|
|
public void ToggleDoor()
|
|
{
|
|
isOpen = !isOpen;
|
|
|
|
// 遍历所有门页进行旋转
|
|
foreach (var leaf in doorLeaves)
|
|
{
|
|
if (leaf == null || leaf.doorTransform == null) continue;
|
|
|
|
Vector3 currentRot = leaf.doorTransform.localEulerAngles;
|
|
// 关门目标为 0,开门目标为 leaf.openAngle
|
|
float targetY = isOpen ? leaf.openAngle : 0f;
|
|
|
|
Vector3 targetRotation = new Vector3(currentRot.x, targetY, currentRot.z);
|
|
|
|
// --- DOTween 核心代码 ---
|
|
|
|
// 1. 杀掉该对象上可能正在运行的旋转动画,防止冲突
|
|
leaf.doorTransform.DOKill();
|
|
|
|
// 2. 创建新动画
|
|
leaf.doorTransform.DOLocalRotate(targetRotation, duration)
|
|
.SetEase(animationEase);
|
|
}
|
|
}
|
|
}
|
|
}
|