using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using VRTK; /// /// 自带重力 松开可自行落下的门 /// [RequireComponent(typeof(VRTK_InteractableObject))] [RequireComponent(typeof(VRInterStepNode))] public class SimpleDoor : MonoBehaviour,IStepNodeAction { VRTK_InteractableObject interactableObject; UnityAction openDoorEvent; UnityAction closeDoorEvent; Rigidbody thisRigidbody; HingeJoint thisHingeJoint; JointLimits defultLimits; public AutoFixedChaXiao chaXiao; //抓取时执行 public event UnityAction OnGrabbedEvent; //放下重力影响完成后执行 public event UnityAction UnGrabbedWaitGravityEvent; //旋转角度 public Vector3 rotateAxis; protected void Awake() { thisRigidbody = this.GetComponent(); thisHingeJoint = this.GetComponent(); defultLimits = thisHingeJoint.limits; interactableObject = this.GetComponent(); interactableObject.InteractableObjectUngrabbed += InteractableObjectUngrabbed; interactableObject.InteractableObjectGrabbed += InteractableObjectGrabbed; interactableObject.touchHighlightColor = Color.red; interactableObject.touchHighlightColor.a=0.3f; SetGrabbable(false);//开始时禁止交互 //chaXiao = this.GetComponentInChildren(); if (rotateAxis == Vector3.zero||rotateAxis.magnitude!=1) { Debug.LogError($"VR交互门:{this.gameObject.name}指定的旋转轴无效!"); } } protected void InteractableObjectGrabbed(object sender, InteractableObjectEventArgs e) { OnGrabbedEvent?.Invoke(); OnGrabbed(); } //放开门时 等待3秒后再判断门是否打开或关上 protected virtual void InteractableObjectUngrabbed(object sender, InteractableObjectEventArgs e) { UnGrabbed(); } //放手后再起抓起物体时取消判定逻辑 void OnGrabbed() { if (IsInvoking("WaitGravity")) CancelInvoke("WaitGravity"); } protected virtual void UnGrabbed() { //if (IsInvoking("WaitGravity")) // CancelInvoke("WaitGravity"); Invoke("WaitGravity", 3f); } void WaitGravity() { UnGrabbedWaitGravityEvent?.Invoke(); UnGrabbedCheckDoorPos();//结束抓取时主动检测位置 } /// /// 主动操作完 3秒后/同步触发时 检查当前门的位置 执行门开/关事件 /// public void UnGrabbedCheckDoorPos() { float currentAngle = 0; if (rotateAxis.x == 1) { currentAngle = this.transform.localEulerAngles.x; } else if (rotateAxis.y == 1) { currentAngle = this.transform.localEulerAngles.y; } else { currentAngle = this.transform.localEulerAngles.z; } if (currentAngle > 180) currentAngle -= 360; Debug.Log("放手时旋转轴角度为:" + currentAngle); if (Mathf.Abs(currentAngle) > 30) //松手2秒后 角度仍大于30度 可以确定门不会自动关上了 { Debug.Log($"松手时角度大小:{currentAngle},门打开了"); if (openDoorEvent != null)//关注打开事件时 执行打开事件后 { openDoorEvent.Invoke(); } } else//小于30度 开门角度不够 重力影响下自动闭合了 { Debug.Log($"松手时角度大小:{currentAngle},角度不够判定关闭"); if (closeDoorEvent != null) { closeDoorEvent.Invoke(); } } } public void Active(ProcessEnum stepName, UnityAction nodeFinishedEvent) { SetGrabbable(true); thisRigidbody.isKinematic = false; if (stepName == ProcessEnum.teardown)//拆卸流程需要把门打开 { openDoorEvent += nodeFinishedEvent; } else if (stepName == ProcessEnum.assemble)//组装流程需要把门关上 { closeDoorEvent += nodeFinishedEvent; } chaXiao?.Active(stepName, null); } public void UnActive(ProcessEnum stepName) { SetGrabbable(false); GetComponent().isKinematic = true; openDoorEvent = null; closeDoorEvent = null; chaXiao?.UnActive(stepName); } //启用 /禁用门交互 public void SetGrabbable(bool grabbable) { interactableObject.isGrabbable = grabbable; } //改变铰链限制度数 保持当前度数 public void KeepNowAngle() { float currentAngle=0; if (rotateAxis.x == 1) { currentAngle = this.transform.localEulerAngles.x; } else if (rotateAxis.y == 1) { currentAngle = this.transform.localEulerAngles.y; } else { currentAngle = this.transform.localEulerAngles.z; } Debug.Log("锁住时当前角度为" + currentAngle); if (currentAngle > 180) currentAngle -= 360; //else // currentAngle = 0; JointLimits limits = thisHingeJoint.limits; limits.max = defultLimits.max + currentAngle - 0.5f; limits.min = defultLimits.max + currentAngle; thisHingeJoint.limits = limits; } //重置铰链限制 public void ReturnDefultLimit() { //Debug.Log("解锁"); Debug.Log(this.transform.localEulerAngles.z); thisHingeJoint.limits = defultLimits; } }