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($"[Door] 收到交互请求!当前状态 isOpen: {isOpen}"); 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); } } } }