美文网首页
OpenXR开发实战项目之VR Interaction Fram

OpenXR开发实战项目之VR Interaction Fram

作者: TonyWan_AR | 来源:发表于2022-05-03 15:21 被阅读0次

    一、框架视图

    二、关键代码

    GrabAction

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    using UnityEngine.Events;
    
    namespace BNG {
    
        public class GrabAction : GrabbableEvents {
    
            public GrabberEvent OnGrabEvent;
    
            Grabbable g;
    
            float lastGrabTime = 0;
    
            float minTimeBetweenGrabs = 0.2f; // In Seconds
    
            public override void OnGrab(Grabber grabber) {
    
                if(g == null) {
    
                    g = GetComponent<Grabbable>();
    
                }
    
                g.DropItem(grabber, false, false);
    
    
    
                if(grabber.RemoteGrabbingItem || grabber.HoldingItem) {
    
                    return;
    
                }
    
    
    
                if (OnGrabEvent != null) {
    
                    if(Time.time - lastGrabTime >= minTimeBetweenGrabs) {
    
                        OnGrabEvent.Invoke(grabber);
    
                        lastGrabTime = Time.time;
    
                    }
    
                }
    
            }
    
        }
    
    }
    
    

    GrabbableHighlight

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    namespace BNG {
    
        public class GrabbableHighlight : GrabbableEvents {
    
            public bool HighlightOnGrabbable = true;
    
            public bool HighlightOnRemoteGrabbable = true;
    
            public override void OnGrab(Grabber grabber) {
    
                UnhighlightItem();
    
            }
    
            public override void OnBecomesClosestGrabbable(ControllerHand touchingHand) {
    
                if (HighlightOnGrabbable) {
    
                    HighlightItem();
    
                }
    
            }
    
            public override void OnNoLongerClosestGrabbable(ControllerHand touchingHand) {
    
                if (HighlightOnGrabbable) {
    
                    UnhighlightItem();
    
                }
    
            }
    
            public override void OnBecomesClosestRemoteGrabbable(ControllerHand touchingHand) {
    
                if (HighlightOnRemoteGrabbable) {
    
                    HighlightItem();
    
                }
    
            }
    
            public override void OnNoLongerClosestRemoteGrabbable(ControllerHand touchingHand) {
    
                if (HighlightOnRemoteGrabbable) {
    
                    UnhighlightItem();
    
                }
    
            }
    
            public void HighlightItem() {
    
    
    
            }
    
            public void UnhighlightItem() {
    
            }
    
        }
    
    }
    
    

    UIPointer

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    using UnityEngine.EventSystems;
    
    using UnityEngine.UI;
    
    namespace BNG {
    
        public class UIPointer : MonoBehaviour {
    
            [Tooltip("The controller side this pointer is on")]
    
            public ControllerHand ControllerSide = ControllerHand.Right;
    
            [Tooltip("If true this object will update the VRUISystem's Left or Right Transform property")]
    
            public bool AutoUpdateUITransforms = true;
    
            public GameObject cursor;
    
            private GameObject _cursor;
    
            [Tooltip("If true the cursor and LineRenderer will be Hidden. Otherwise it will still be show at a fixed length")]
    
            public bool HidePointerIfNoObjectsFound = true;
    
            [Tooltip("How long the line / cursor should extend if no objects are found to point at")]
    
            public float FixedPointerLength = 0.5f;
    
            [Tooltip("If true the cursor object will scale based on how far away the pointer is from the origin. A cursor far away will have a larger cusor than one up close.")]
    
            public bool CursorScaling = true;
    
            [Tooltip("Minimum scale of the Cursor object if CursorScaling is enabled")]
    
            public float CursorMinScale = 0.6f;
    
            public float CursorMaxScale = 6.0f;
    
    
    
            private Vector3 _cursorInitialLocalScale;
    
    
    
            [Tooltip("Example : 0.5 = Line Goes Half Way. 1 = Line reaches end.")]
    
            public float LineDistanceModifier = 0.8f;
    
            VRUISystem uiSystem;
    
            PointerEvents selectedPointerEvents;
    
            PointerEventData data;
    
            [Tooltip("LineRenderer to use when showing a valid UI Canvas. Leave null to attempt a GetComponent<> on this object.")]
    
            public LineRenderer lineRenderer;
    
            void Awake() {
    
                if(cursor) {
    
                    _cursor = GameObject.Instantiate(cursor);
    
                    _cursor.transform.SetParent(transform);
    
                    _cursorInitialLocalScale = transform.localScale;
    
                }
    
    
    
                if (lineRenderer == null) {
    
                    lineRenderer = GetComponent<LineRenderer>();
    
                }
    
                uiSystem = VRUISystem.Instance;         
    
            }
    
            void OnEnable() {
    
    
    
                if (AutoUpdateUITransforms && ControllerSide == ControllerHand.Left) {
    
                    uiSystem.LeftPointerTransform = this.transform;
    
                }
    
                else if (AutoUpdateUITransforms && ControllerSide == ControllerHand.Right) {
    
                    uiSystem.RightPointerTransform = this.transform;
    
                }
    
                uiSystem.UpdateControllerHand(ControllerSide);
    
            }
    
            public void Update() {
    
                data = uiSystem.EventData;
    
                // Can bail early if not looking at anything
    
                if (data == null || data.pointerCurrentRaycast.gameObject == null) {
    
    
    
                    HidePointer();
    
    
    
                    return;
    
                }
    
    
    
                if (_cursor != null ) {
    
                    bool lookingAtUI = data.pointerCurrentRaycast.module.GetType() == typeof(GraphicRaycaster);
    
                    selectedPointerEvents = data.pointerCurrentRaycast.gameObject.GetComponent<PointerEvents>();
    
                    bool lookingAtPhysicalObject = selectedPointerEvents != null;
    
    
    
                    if(lookingAtPhysicalObject) {
    
                        if (data.pointerCurrentRaycast.distance > selectedPointerEvents.MaxDistance) {
    
                            HidePointer();
    
                            return;
    
                        }
    
                    }
    
    
    
    
    
                    if(!lookingAtUI && !lookingAtPhysicalObject) {
    
                        HidePointer();
    
                        return;
    
                    }
    
    
    
                    float distance = Vector3.Distance(transform.position, data.pointerCurrentRaycast.worldPosition);
    
                    _cursor.transform.localPosition = new Vector3(0, 0, distance - 0.0001f);               
    
                    _cursor.transform.rotation = Quaternion.FromToRotation(Vector3.forward, data.pointerCurrentRaycast.worldNormal);
    
    
    
                    float cameraDist = Vector3.Distance(Camera.main.transform.position, _cursor.transform.position);
    
                    _cursor.transform.localScale = _cursorInitialLocalScale * Mathf.Clamp(cameraDist, CursorMinScale, CursorMaxScale);
    
                    _cursor.SetActive(data.pointerCurrentRaycast.distance > 0);
    
                }
    
    
    
                if (lineRenderer) {
    
                    lineRenderer.useWorldSpace = false;
    
                    lineRenderer.SetPosition(0, Vector3.zero);
    
                    lineRenderer.SetPosition(1, new Vector3(0, 0 , Vector3.Distance(transform.position, data.pointerCurrentRaycast.worldPosition) * LineDistanceModifier));
    
                    lineRenderer.enabled = data.pointerCurrentRaycast.distance > 0;
    
                }
    
            }
    
            public virtual void HidePointer() {
    
    
    
                if(HidePointerIfNoObjectsFound) {
    
                    _cursor.SetActive(false);
    
                    lineRenderer.enabled = false;
    
                }
    
    
    
                else {
    
                    if (_cursor) {
    
                        _cursor.SetActive(false);
    
                    }
    
    
    
                    if (lineRenderer) {
    
                        lineRenderer.useWorldSpace = false;
    
                        lineRenderer.SetPosition(0, Vector3.zero);
    
                        lineRenderer.SetPosition(1, new Vector3(0, 0, FixedPointerLength * LineDistanceModifier));
    
                        lineRenderer.enabled = true;
    
                    }
    
                }
    
            }
    
        }
    
    }
    
    

    GrabbablesInTrigger

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    namespace BNG {
    
        public class GrabbablesInTrigger : MonoBehaviour {
    
            public Dictionary<Collider, Grabbable> NearbyGrabbables;
    
            public Dictionary<Collider, Grabbable> ValidGrabbables;
    
            public Grabbable ClosestGrabbable;
    
            public Dictionary<Collider, Grabbable> ValidRemoteGrabbables;
    
            public Grabbable ClosestRemoteGrabbable;
    
            public bool FireGrabbableEvents = true;
    
    
    
            private Grabbable _closest;
    
            private float _lastDistance;
    
            private float _thisDistance;
    
            private Dictionary<Collider, Grabbable> _valids;
    
            private Dictionary<Collider, Grabbable> _filtered;
    
            void Start() {
    
                NearbyGrabbables = new Dictionary<Collider, Grabbable>();
    
                ValidGrabbables = new Dictionary<Collider, Grabbable>();
    
                ValidRemoteGrabbables = new Dictionary<Collider, Grabbable>();
    
            }
    
            void Update() {
    
                updateClosestGrabbable();
    
                updateClosestRemoteGrabbables();
    
            }
    
            void updateClosestGrabbable() {
    
                NearbyGrabbables = SanitizeGrabbables(NearbyGrabbables);
    
                ValidGrabbables = GetValidGrabbables(NearbyGrabbables);
    
                ClosestGrabbable = GetClosestGrabbable(ValidGrabbables);
    
            }
    
            void updateClosestRemoteGrabbables() {
    
                ClosestRemoteGrabbable = GetClosestGrabbable(ValidRemoteGrabbables, true);
    
                if (ClosestGrabbable != null) {
    
                    ClosestRemoteGrabbable = null;
    
                }
    
            }
    
            public virtual Grabbable GetClosestGrabbable(Dictionary<Collider, Grabbable> grabbables, bool remoteOnly = false) {
    
                _closest = null;
    
                _lastDistance = 9999f;
    
                if(grabbables == null) {
    
                    return null;
    
                }
    
                foreach (var kvp in grabbables) {               
    
                    if (kvp.Value == null || !kvp.Value.IsGrabbable()) {
    
                        continue;
    
                    }
    
                    _thisDistance = Vector3.Distance(kvp.Value.transform.position, transform.position);
    
                    if (_thisDistance < _lastDistance && kvp.Value.isActiveAndEnabled) {
    
                        if (remoteOnly && !kvp.Value.RemoteGrabbable) {
    
                            continue;
    
                        }
    
                        if (remoteOnly && _thisDistance > kvp.Value.RemoteGrabDistance) {
    
                            continue;
    
                        }
    
                        // This is now our closest grabbable
    
                        _lastDistance = _thisDistance;
    
                        _closest = kvp.Value;
    
                    }
    
                }
    
                return _closest;
    
            }
    
            public Dictionary<Collider, Grabbable> GetValidGrabbables(Dictionary<Collider, Grabbable> grabs) {
    
                _valids = new Dictionary<Collider, Grabbable>();
    
                if (grabs == null) {
    
                    return _valids;
    
                }
    
                foreach (var kvp in grabs) {
    
                    if (isValidGrabbale(kvp.Key, kvp.Value) && !_valids.ContainsKey(kvp.Key)) {
    
                        _valids.Add(kvp.Key, kvp.Value);
    
                    }
    
                }
    
                return _valids;
    
            }
    
            protected virtual bool isValidGrabbale(Collider col, Grabbable grab) {
    
                if (col == null || grab == null || !grab.isActiveAndEnabled || !col.enabled) {
    
                    return false;
    
                }
    
                else if (!grab.IsGrabbable()) {
    
                    return false;
    
                }
    
                else if(grab.GetComponent<SnapZone>() != null && grab.GetComponent<SnapZone>().HeldItem == null) {
    
                    return false;
    
                }
    
                else if (grab == ClosestGrabbable) {
    
                    if (grab.BreakDistance > 0 && Vector3.Distance(grab.transform.position, transform.position) > grab.BreakDistance) {
    
                        return false;
    
                    }
    
                }
    
                return true;
    
            }
    
            public virtual Dictionary<Collider, Grabbable> SanitizeGrabbables(Dictionary<Collider, Grabbable> grabs) {
    
                _filtered = new Dictionary<Collider, Grabbable>();
    
                if (grabs == null) {
    
                    return _filtered;
    
                }
    
                foreach (var g in grabs) {
    
                    if (g.Key != null && g.Key.enabled && g.Value.isActiveAndEnabled) {
    
                        if (g.Value.BreakDistance > 0 && Vector3.Distance(g.Key.transform.position, transform.position) > g.Value.BreakDistance) {
    
                            continue;
    
                        }
    
                        _filtered.Add(g.Key, g.Value);
    
                    }
    
                }
    
                return _filtered;
    
            }
    
            public virtual void AddNearbyGrabbable(Collider col, Grabbable grabObject) {
    
                if(NearbyGrabbables == null) {
    
                    NearbyGrabbables = new Dictionary<Collider, Grabbable>();
    
                }
    
                if (grabObject != null && !NearbyGrabbables.ContainsKey(col)) {
    
                    NearbyGrabbables.Add(col, grabObject);
    
                }
    
            }
    
            public virtual void RemoveNearbyGrabbable(Collider col, Grabbable grabObject) {
    
                if (grabObject != null && NearbyGrabbables != null && NearbyGrabbables.ContainsKey(col)) {
    
                    NearbyGrabbables.Remove(col);
    
                }
    
            }
    
            public virtual void RemoveNearbyGrabbable(Grabbable grabObject) {
    
                if (grabObject != null) {
    
                    foreach (var x in NearbyGrabbables) {
    
                        if (x.Value == grabObject) {
    
                            NearbyGrabbables.Remove(x.Key);
    
                            break;
    
                        }
    
                    }
    
                }
    
            }
    
            public virtual void AddValidRemoteGrabbable(Collider col, Grabbable grabObject) {
    
    
    
                if(col == null || grabObject == null) {
    
                    return;
    
                }
    
                if (ValidRemoteGrabbables == null) {
    
                    ValidRemoteGrabbables = new Dictionary<Collider, Grabbable>();
    
                }
    
                try {
    
                    if (grabObject != null && grabObject.RemoteGrabbable && col != null && !ValidRemoteGrabbables.ContainsKey(col)) {
    
    
    
                        ValidRemoteGrabbables.Add(col, grabObject);
    
                    }
    
                }
    
                catch(System.Exception e) {
    
                    Debug.Log("Could not add Collider " + col.transform.name + " " + e.Message);
    
                }
    
            }
    
            public virtual void RemoveValidRemoteGrabbable(Collider col, Grabbable grabObject) {
    
                if (grabObject != null && ValidRemoteGrabbables != null && ValidRemoteGrabbables.ContainsKey(col)) {
    
                    ValidRemoteGrabbables.Remove(col);
    
                }
    
            }
    
            void OnTriggerEnter(Collider other) {
    
                Grabbable g = other.GetComponent<Grabbable>();
    
                if (g != null) {
    
                    AddNearbyGrabbable(other, g);
    
                    return;
    
                }
    
                GrabbableChild gc = other.GetComponent<GrabbableChild>();
    
                if (gc != null && gc.ParentGrabbable != null) {
    
                    AddNearbyGrabbable(other, gc.ParentGrabbable);
    
                    return;
    
                }
    
            }
    
            void OnTriggerExit(Collider other) {
    
                Grabbable g = other.GetComponent<Grabbable>();
    
                if (g != null) {
    
                    RemoveNearbyGrabbable(other, g);
    
                    return;
    
                }
    
                GrabbableChild gc = other.GetComponent<GrabbableChild>();
    
                if (gc != null) {
    
                    RemoveNearbyGrabbable(other, gc.ParentGrabbable);
    
                    return;
    
                }
    
            }
    
        }
    
    }
    
    

    CharacterIK

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    namespace BNG {
    
        public class CharacterIK : MonoBehaviour {
    
    
    
            public Transform FollowLeftController;
    
            public Transform FollowRightController;
    
            public Transform FollowLeftFoot;
    
            public Transform FollowRightFoot;
    
            public Transform FollowHead;
    
            public float FootYPosition = 0;
    
            public bool IKActive = true;
    
    
    
            public bool IKFeetActive = true;
    
    
    
            public bool HideHead = true;
    
            public bool HideLeftArm = false;
    
            public bool HideRightArm = false;
    
            public bool HideLeftHand = false;
    
            public bool HideRightHand = false;
    
            public bool HideLegs = false;
    
            public Transform HipsJoint;
    
            public CharacterController FollowPlayer;
    
            Transform headBone;
    
            Transform leftShoulderJoint;
    
            Transform rightShoulderJoint;
    
            Transform leftHandJoint;
    
            Transform rightHandJoint;
    
            Animator animator;
    
            public float HipOffset = 0;
    
            void Start() {
    
                animator = GetComponent<Animator>();
    
                headBone = animator.GetBoneTransform(HumanBodyBones.Head);
    
                leftHandJoint = animator.GetBoneTransform(HumanBodyBones.LeftHand);
    
                rightHandJoint = animator.GetBoneTransform(HumanBodyBones.RightHand);
    
                leftShoulderJoint = animator.GetBoneTransform(HumanBodyBones.LeftShoulder);
    
                rightShoulderJoint = animator.GetBoneTransform(HumanBodyBones.RightShoulder);
    
            }
    
            public Vector3 hideBoneScale = new Vector3(0.0001f, 0.0001f, 0.0001f);
    
            void Update() {
    
                if (headBone != null) {
    
                    headBone.localScale = HideHead ? Vector3.zero : Vector3.one;
    
                }
    
                if (leftShoulderJoint != null) {
    
                    leftShoulderJoint.localScale = HideLeftArm ? hideBoneScale : Vector3.one;
    
                }
    
                if (rightShoulderJoint != null) {
    
                    rightShoulderJoint.localScale = HideRightArm ? hideBoneScale : Vector3.one;
    
                }
    
                if (leftHandJoint != null) {
    
                    leftHandJoint.localScale = HideLeftHand ? Vector3.zero : Vector3.one;
    
                }
    
                if (rightHandJoint != null) {
    
                    rightHandJoint.localScale = HideRightHand ? Vector3.zero : Vector3.one;
    
                }
    
                if(HipsJoint) {
    
                    HipsJoint.localScale = HideLegs ? Vector3.zero : Vector3.one;
    
                }
    
                Transform hipJoint = animator.GetBoneTransform(HumanBodyBones.RightShoulder);           
    
            }
    
    
    
            void OnAnimatorIK() {
    
                if (animator) {               
    
                    if (IKActive) {
    
                        if (FollowHead != null) {
    
                            animator.SetLookAtWeight(1);
    
                            animator.SetLookAtPosition(FollowHead.position);
    
                        }
    
                        if (FollowLeftController != null) {
    
                            animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
    
                            animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
    
                            animator.SetIKPosition(AvatarIKGoal.LeftHand, FollowLeftController.position);
    
                            animator.SetIKRotation(AvatarIKGoal.LeftHand, FollowLeftController.rotation);
    
                        }
    
                        if (FollowRightController != null) {
    
                            animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
    
                            animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
    
                            animator.SetIKPosition(AvatarIKGoal.RightHand, FollowRightController.position);
    
                            animator.SetIKRotation(AvatarIKGoal.RightHand, FollowRightController.rotation);
    
                        }
    
                        if(IKFeetActive) {
    
                            if (FollowLeftFoot != null) {
    
                                animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1);                           
    
                                animator.SetIKPosition(AvatarIKGoal.LeftFoot, new Vector3(FollowLeftFoot.position.x, FootYPosition, FollowLeftFoot.position.z));
    
                            }
    
                            if (FollowRightFoot != null) {
    
                                animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
    
                                animator.SetIKPosition(AvatarIKGoal.RightFoot, new Vector3(FollowRightFoot.position.x, FootYPosition, FollowRightFoot.position.z));
    
                            }
    
    
    
                        }
    
                        else {
    
                            if (FollowLeftFoot != null) {
    
                                animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 0);
    
                            }
    
                            if (FollowRightFoot != null) {
    
                                animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 0);
    
                            }
    
                        }
    
                    }
    
                    else {
    
                        animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 0);
    
                        animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 0);
    
                        animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
    
                        animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);
    
                        animator.SetLookAtWeight(0);
    
                    }
    
                }
    
            }
    
        }
    
    }
    
    

    SteeringWheel

    
    using System;
    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    using UnityEngine.UI;
    
    namespace BNG {
    
        public class SteeringWheel : GrabbableEvents {
    
            [Header("Rotation Limits")]
    
    
    
            public float MinAngle = -360f;
    
            public float MaxAngle = 360f;
    
            [Header("Rotation Object")]
    
            public Transform RotatorObject;
    
            [Header("Rotation Speed")]
    
            public float RotationSpeed = 0f;
    
            [Header("Two-Handed Option")]
    
            public bool AllowTwoHanded = true;
    
            [Header("Return to Center")]
    
            public bool ReturnToCenter = false;
    
            public float ReturnToCenterSpeed = 45;
    
            [Header("Debug Options")]
    
            public Text DebugText;
    
            [Header("Events")]
    
            public FloatEvent onAngleChange;
    
            public FloatEvent onValueChange;
    
            [Header("Editor Option")]
    
            public bool ShowEditorGizmos = true;
    
            public float Angle {
    
                get {
    
                    return Mathf.Clamp(smoothedAngle, MinAngle, MaxAngle);
    
                }
    
            }
    
    
    
            public float RawAngle {
    
                get {
    
                    return targetAngle;
    
                }
    
            }
    
            public float ScaleValue {
    
                get {
    
                    return GetScaledValue(Angle, MinAngle, MaxAngle);
    
                }
    
            }
    
            public float ScaleValueInverted {
    
                get {
    
                    return ScaleValue * -1;
    
                }
    
            }
    
            public float AngleInverted {
    
                get {
    
                    return Angle * -1;
    
                }
    
            }
    
            public Grabber PrimaryGrabber {
    
                get {
    
                    return GetPrimaryGrabber();
    
                }
    
            }
    
            public Grabber SecondaryGrabber {
    
                get {
    
                    return GetSecondaryGrabber();
    
                }
    
            }
    
            protected Vector3 rotatePosition;
    
            protected Vector3 previousPrimaryPosition;
    
            protected Vector3 previousSecondaryPosition;
    
            protected float targetAngle;
    
            protected float previousTargetAngle;
    
            protected float smoothedAngle;
    
            void Update() {
    
                if (grab.BeingHeld) {
    
                    UpdateAngleCalculations();
    
                }
    
                else if (ReturnToCenter) {
    
                    ReturnToCenterAngle();
    
                }
    
    
    
                ApplyAngleToSteeringWheel(Angle);
    
                CallEvents();
    
                UpdatePreviewText();
    
                UpdatePreviousAngle(targetAngle);
    
            }       
    
            public virtual void UpdateAngleCalculations() {
    
                float angleAdjustment = 0f;
    
    
    
                if (PrimaryGrabber) {
    
                    rotatePosition = transform.InverseTransformPoint(PrimaryGrabber.transform.position);
    
                    rotatePosition = new Vector3(rotatePosition.x, rotatePosition.y, 0);
    
                    angleAdjustment += GetRelativeAngle(rotatePosition, previousPrimaryPosition);
    
                    previousPrimaryPosition = rotatePosition;
    
                }
    
                if (AllowTwoHanded && SecondaryGrabber != null) {
    
                    rotatePosition = transform.InverseTransformPoint(SecondaryGrabber.transform.position);
    
                    rotatePosition = new Vector3(rotatePosition.x, rotatePosition.y, 0);
    
                    angleAdjustment += GetRelativeAngle(rotatePosition, previousSecondaryPosition);
    
                    previousSecondaryPosition = rotatePosition;
    
                }
    
                if(PrimaryGrabber != null && SecondaryGrabber != null) {
    
                    angleAdjustment *= 0.5f;
    
                }
    
    
    
                targetAngle -= angleAdjustment;
    
    
    
                if(RotationSpeed == 0) {
    
                    smoothedAngle = targetAngle;
    
                }
    
    
    
                else {
    
                    smoothedAngle = Mathf.Lerp(smoothedAngle, targetAngle, Time.deltaTime * RotationSpeed);
    
                }
    
                if (MinAngle != 0 && MaxAngle != 0) {
    
                    targetAngle = Mathf.Clamp(targetAngle, MinAngle, MaxAngle);
    
                    smoothedAngle = Mathf.Clamp(smoothedAngle, MinAngle, MaxAngle);
    
                }
    
            }
    
            public float GetRelativeAngle(Vector3 position1, Vector3 position2) {
    
                if (Vector3.Cross(position1, position2).z < 0) {
    
                    return -Vector3.Angle(position1, position2);
    
                }
    
                return Vector3.Angle(position1, position2);
    
            }
    
            public virtual void ApplyAngleToSteeringWheel(float angle) {
    
                RotatorObject.localEulerAngles = new Vector3(0, 0, angle);
    
            }
    
            public virtual void UpdatePreviewText() {
    
                if (DebugText) {
    
                    DebugText.text = String.Format("{0}\n{1}", (int)AngleInverted, (ScaleValueInverted).ToString("F2"));
    
                }
    
            }
    
            public virtual void CallEvents() {
    
                if (targetAngle != previousTargetAngle) {
    
                    onAngleChange.Invoke(targetAngle);
    
                }
    
                onValueChange.Invoke(ScaleValue);
    
            }
    
            public override void OnGrab(Grabber grabber) {
    
                if(grabber == SecondaryGrabber) {
    
                    previousSecondaryPosition = transform.InverseTransformPoint(SecondaryGrabber.transform.position);
    
                    previousSecondaryPosition = new Vector3(previousSecondaryPosition.x, previousSecondaryPosition.y, 0);
    
                }
    
                else {
    
                    previousPrimaryPosition = transform.InverseTransformPoint(PrimaryGrabber.transform.position);
    
                    previousPrimaryPosition = new Vector3(previousPrimaryPosition.x, previousPrimaryPosition.y, 0);
    
                }
    
            }
    
            public virtual void ReturnToCenterAngle() {
    
                bool wasUnderZero = smoothedAngle < 0;
    
                if (smoothedAngle > 0) {
    
                    smoothedAngle -= Time.deltaTime * ReturnToCenterSpeed;
    
                }
    
                else if (smoothedAngle < 0) {
    
                    smoothedAngle += Time.deltaTime * ReturnToCenterSpeed;
    
                }
    
                if (wasUnderZero && smoothedAngle > 0) {
    
                    smoothedAngle = 0;
    
                }
    
                else if (!wasUnderZero && smoothedAngle < 0) {
    
                    smoothedAngle = 0;
    
                }
    
                if (smoothedAngle < 0.02f && smoothedAngle > -0.02f) {
    
                    smoothedAngle = 0;
    
                }
    
    
    
                targetAngle = smoothedAngle;
    
            }
    
            public Grabber GetPrimaryGrabber() {
    
                if (grab.HeldByGrabbers != null) {
    
                    for (int x = 0; x < grab.HeldByGrabbers.Count; x++) {
    
                        Grabber g = grab.HeldByGrabbers[x];
    
                        if (g.HandSide == ControllerHand.Right) {
    
                            return g;
    
                        }
    
                    }
    
                }
    
                return null;
    
            }
    
            public Grabber GetSecondaryGrabber() {
    
                if (grab.HeldByGrabbers != null) {
    
                    for (int x = 0; x < grab.HeldByGrabbers.Count; x++) {
    
                        Grabber g = grab.HeldByGrabbers[x];
    
                        if (g.HandSide == ControllerHand.Left) {
    
                            return g;
    
                        }
    
                    }
    
                }
    
                return null;
    
            }
    
            public virtual void UpdatePreviousAngle(float angle) {
    
                previousTargetAngle = angle;
    
            }
    
            public virtual float GetScaledValue(float value, float min, float max) {
    
                float range = (max - min) / 2f;
    
                float returnValue = ((value - min) / range) - 1;
    
                return returnValue;
    
            }               
    
    #if UNITY_EDITOR
    
            public void OnDrawGizmosSelected() {
    
                if (ShowEditorGizmos && !Application.isPlaying) {
    
                    Vector3 origin = transform.position;
    
                    float rotationDifference = MaxAngle - MinAngle;
    
                    float lineLength = 0.1f;
    
                    float arcLength = 0.1f;
    
                    UnityEditor.Handles.color = Color.cyan;
    
                    Vector3 minPosition = origin + Quaternion.AngleAxis(MinAngle, transform.forward) * transform.up * lineLength;
    
                    Vector3 maxPosition = origin + Quaternion.AngleAxis(MaxAngle, transform.forward) * transform.up * lineLength;
    
                    UnityEditor.Handles.DrawLine(origin, minPosition);
    
                    UnityEditor.Handles.DrawLine(origin, maxPosition);
    
                    Debug.DrawLine(transform.position, origin + Quaternion.AngleAxis(0, transform.up) * transform.up * lineLength, Color.magenta);
    
                    if (rotationDifference == 180) {
    
                        minPosition = origin + Quaternion.AngleAxis(MinAngle + 0.01f, transform.up) * transform.up * lineLength;
    
                    }
    
    
    
                    Vector3 cross = Vector3.Cross(minPosition - origin, maxPosition - origin);
    
                    if (rotationDifference > 180) {
    
                        cross = Vector3.Cross(maxPosition - origin, minPosition - origin);
    
                    }
    
                    UnityEditor.Handles.color = new Color(0, 255, 255, 0.1f);
    
                    UnityEditor.Handles.DrawSolidArc(origin, cross, minPosition - origin, rotationDifference, arcLength);
    
                }
    
            }
    
    #endif
    
        }
    
    }
    
    

    HandController

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    namespace BNG {
    
        public class HandController : MonoBehaviour {
    
            public Transform HandAnchor;
    
            public bool ResetHandAnchorPosition = true;
    
            public Animator HandAnimator;
    
            public HandPoser handPoser;
    
            public AutoPoser autoPoser;
    
            public bool AutoPoseWhenNoGrabbable = false;
    
    
    
            public float HandAnimationSpeed = 20f;
    
            public Grabber grabber;
    
    
    
            public float GripAmount;
    
            private float _prevGrip;
    
            public float PointAmount;
    
            private float _prevPoint;
    
    
    
            public float ThumbAmount;
    
            private float _prevThumb;
    
            public int PoseId;
    
            ControllerOffsetHelper offset;
    
            InputBridge input;
    
            Rigidbody rigid;
    
            Transform offsetTransform;
    
            Vector3 offsetPosition {
    
                get {
    
                    if(offset) {
    
                        return offset.OffsetPosition;
    
                    }
    
                    return Vector3.zero;
    
                }
    
            }
    
            Vector3 offsetRotation {
    
                get {
    
                    if (offset) {
    
                        return offset.OffsetRotation;
    
                    }
    
                    return Vector3.zero;
    
                }
    
            }
    
            void Start() {
    
                rigid = GetComponent<Rigidbody>();
    
                offset = GetComponent<ControllerOffsetHelper>();
    
                offsetTransform = new GameObject("OffsetHelper").transform;
    
                offsetTransform.parent = transform;
    
                if (HandAnchor) {
    
                    transform.parent = HandAnchor;
    
                    offsetTransform.parent = HandAnchor;
    
                    if (ResetHandAnchorPosition) {
    
                        transform.localPosition = offsetPosition;
    
                        transform.localEulerAngles = offsetRotation;
    
                    }
    
                }
    
    
    
                if(grabber == null) {
    
                    grabber = GetComponentInChildren<Grabber>();
    
                }
    
                if(grabber != null) {
    
                    grabber.onAfterGrabEvent.AddListener(OnGrabberGrabbed);
    
                    grabber.onReleaseEvent.AddListener(OnGrabberReleased);
    
                }
    
    
    
                SetHandAnimator();
    
                input = InputBridge.Instance;
    
            }
    
            public void Update() {
    
                CheckForGrabChange();
    
                UpdateFromInputs();
    
    
    
                UpdateAnimimationStates();
    
    
    
                UpdateHandPoser();
    
            }
    
            public GameObject PreviousHeldObject;
    
            public virtual void CheckForGrabChange() {
    
                if(grabber != null) {
    
                    if(grabber.HeldGrabbable == null && PreviousHeldObject != null) {                   
    
                        OnGrabDrop();
    
                    }
    
                    else if(grabber.HeldGrabbable != null && !GameObject.ReferenceEquals(grabber.HeldGrabbable.gameObject, PreviousHeldObject)) {
    
                        OnGrabChange(grabber.HeldGrabbable.gameObject);
    
                    }
    
                }
    
            }
    
            public virtual void OnGrabChange(GameObject newlyHeldObject) {
    
                if(grabber != null && grabber.HeldGrabbable != null) {
    
                    if (grabber.HeldGrabbable.handPoseType == HandPoseType.AnimatorID) {
    
                        EnableHandAnimator();
    
                    }
    
                    else if (grabber.HeldGrabbable.handPoseType == HandPoseType.AutoPoseOnce) {
    
                        EnableAutoPoser(false);
    
                    }
    
                    else if (grabber.HeldGrabbable.handPoseType == HandPoseType.AutoPoseContinuous) {
    
                        EnableAutoPoser(true);
    
                    }
    
    
    
                    else if (grabber.HeldGrabbable.handPoseType == HandPoseType.HandPose) {
    
    
    
                        if (grabber.HeldGrabbable.SelectedHandPose != null) {
    
                            EnableHandPoser();
    
                        }
    
                        else {
    
                            EnableHandAnimator();
    
                        }
    
    
    
                    }
    
                }
    
                PreviousHeldObject = newlyHeldObject;
    
            }
    
    
    
            public virtual void OnGrabDrop() {
    
    
    
                if(AutoPoseWhenNoGrabbable) {
    
                    EnableAutoPoser(true);
    
                }
    
                else {
    
                    EnableHandAnimator();
    
                    DisableAutoPoser();
    
                }
    
                PreviousHeldObject = null;
    
            }     
    
            public virtual void SetHandAnimator() {
    
                if (HandAnimator == null || !HandAnimator.gameObject.activeInHierarchy) {
    
                    HandAnimator = GetComponentInChildren<Animator>();
    
                }
    
            }
    
    
    
            public virtual void UpdateFromInputs() {
    
                if (grabber == null || !grabber.isActiveAndEnabled) {
    
                    grabber = GetComponentInChildren<Grabber>();
    
                    GripAmount = 0;
    
                    PointAmount = 0;
    
                    ThumbAmount = 0;
    
                    return;
    
                }
    
                if (grabber.HandSide == ControllerHand.Left) {
    
                    GripAmount = input.LeftGrip;
    
                    PointAmount = 1 - input.LeftTrigger;
    
                    PointAmount *= InputBridge.Instance.InputSource == XRInputSource.SteamVR ? 0.25F : 0.5F;
    
    
    
                    if (input.SupportsIndexTouch && input.LeftTriggerNear == false && PointAmount != 0) {
    
                        PointAmount = 1f;
    
                    }
    
    
    
                    else if (!input.SupportsIndexTouch && input.LeftTrigger == 0) {
    
                        PointAmount = 1;
    
                    }
    
                    ThumbAmount = input.LeftThumbNear ? 0 : 1;
    
                }
    
                else if (grabber.HandSide == ControllerHand.Right) {
    
                    GripAmount = input.RightGrip;
    
                    PointAmount = 1 - input.RightTrigger;
    
                    PointAmount *= InputBridge.Instance.InputSource == XRInputSource.SteamVR ? 0.25F : 0.5F;
    
    
    
                    if (input.SupportsIndexTouch && input.RightTriggerNear == false && PointAmount != 0) {
    
                        PointAmount = 1f;
    
                    }
    
    
    
                    else if (!input.SupportsIndexTouch && input.RightTrigger == 0) {
    
                        PointAmount = 1;
    
                    }
    
                    ThumbAmount = input.RightThumbNear ? 0 : 1;
    
                }
    
            }
    
            public bool DoUpdateAnimationStates = true;
    
            public bool DoUpdateHandPoser = true;
    
            public virtual void UpdateAnimimationStates()
    
            {
    
                if(DoUpdateAnimationStates == false) {
    
                    return;
    
                }
    
    
    
                if(IsAnimatorGrabbable() && !HandAnimator.isActiveAndEnabled) {
    
                    EnableHandAnimator();
    
                }
    
    
    
                if (HandAnimator != null && HandAnimator.isActiveAndEnabled && HandAnimator.runtimeAnimatorController != null) {
    
                    _prevGrip = Mathf.Lerp(_prevGrip, GripAmount, Time.deltaTime * HandAnimationSpeed);
    
                    _prevThumb = Mathf.Lerp(_prevThumb, ThumbAmount, Time.deltaTime * HandAnimationSpeed);
    
                    _prevPoint = Mathf.Lerp(_prevPoint, PointAmount, Time.deltaTime * HandAnimationSpeed);
    
    
    
                    HandAnimator.SetFloat("Flex", _prevGrip);
    
                    HandAnimator.SetLayerWeight(1, _prevThumb);
    
                    HandAnimator.SetLayerWeight(2, _prevPoint);
    
    
    
                    if (grabber != null && grabber.HeldGrabbable != null) {
    
                        HandAnimator.SetLayerWeight(0, 0);
    
                        HandAnimator.SetLayerWeight(1, 0);
    
                        HandAnimator.SetLayerWeight(2, 0);
    
                        PoseId = (int)grabber.HeldGrabbable.CustomHandPose;
    
                        if (grabber.HeldGrabbable.ActiveGrabPoint != null) {
    
    
    
                            HandAnimator.SetLayerWeight(0, 1);
    
                            HandAnimator.SetFloat("Flex", 1);
    
                            setAnimatorBlend(grabber.HeldGrabbable.ActiveGrabPoint.IndexBlendMin, grabber.HeldGrabbable.ActiveGrabPoint.IndexBlendMax, PointAmount, 2);
    
    
    
                            setAnimatorBlend(grabber.HeldGrabbable.ActiveGrabPoint.ThumbBlendMin, grabber.HeldGrabbable.ActiveGrabPoint.ThumbBlendMax, ThumbAmount, 1);                     
    
                        }
    
                        else {
    
                            if (grabber.HoldingItem) {
    
                                GripAmount = 1;
    
                                PointAmount = 0;
    
                                ThumbAmount = 0;
    
                            }
    
                        }
    
                        HandAnimator.SetInteger("Pose", PoseId);
    
    
    
                    }
    
                    else {
    
                        HandAnimator.SetInteger("Pose", 0);
    
                    }
    
                }
    
            }
    
            void setAnimatorBlend(float min, float max, float input, int animationLayer) {
    
                HandAnimator.SetLayerWeight(animationLayer, min + (input) * max - min);
    
            }
    
    
    
            public virtual bool IsAnimatorGrabbable() {
    
                return HandAnimator != null && grabber != null && grabber.HeldGrabbable != null && grabber.HeldGrabbable.handPoseType == HandPoseType.AnimatorID;
    
            }
    
            public virtual void UpdateHandPoser() {
    
                if (DoUpdateHandPoser == false) {
    
                    return;
    
                }
    
                if (handPoser == null || !handPoser.isActiveAndEnabled) {
    
                    handPoser = GetComponentInChildren<HandPoser>();
    
                }                       
    
                if(handPoser == null || grabber == null || grabber.HeldGrabbable == null || grabber.HeldGrabbable.handPoseType != HandPoseType.HandPose) {
    
                    return;
    
                }
    
            }
    
            public virtual void EnableHandPoser() {
    
                if(handPoser != null) {
    
                    DisableHandAnimator();
    
                }
    
            }
    
            public virtual void EnableAutoPoser(bool continuous) {
    
                if (autoPoser == null || !autoPoser.gameObject.activeInHierarchy) {
    
                    if(handPoser != null) {
    
                        autoPoser = handPoser.GetComponent<AutoPoser>();
    
                    }
    
                    else {
    
                        autoPoser = GetComponentInChildren<AutoPoser>(false);
    
                    }
    
                }
    
                if (autoPoser != null) {
    
                    autoPoser.UpdateContinuously = continuous;
    
                    if(!continuous) {
    
                        autoPoser.UpdateAutoPoseOnce();
    
                    }
    
                    DisableHandAnimator();
    
                }
    
            }
    
            public virtual void DisableAutoPoser() {
    
                if (autoPoser != null) {
    
                    autoPoser.UpdateContinuously = false;
    
                }
    
            }
    
            public virtual void EnableHandAnimator() {
    
                if (HandAnimator != null && HandAnimator.enabled == false) {
    
                    HandAnimator.enabled = true;
    
                }
    
            }
    
            public virtual void DisableHandAnimator() {
    
                if (HandAnimator != null && HandAnimator.enabled) {
    
                    HandAnimator.enabled = false;
    
                }
    
            }
    
            public virtual void OnGrabberGrabbed(Grabbable grabbed) {
    
                if (grabbed.SelectedHandPose != null && handPoser != null) {
    
                    handPoser.CurrentPose = grabber.HeldGrabbable.SelectedHandPose;
    
                    handPoser.OnPoseChanged();
    
                }
    
            }
    
            public virtual void OnGrabberReleased(Grabbable released) {
    
                OnGrabDrop();
    
            }
    
        }
    
    }
    
    

    Door

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    namespace BNG {
    
        public class Door : MonoBehaviour {
    
            public AudioClip DoorOpenSound;
    
            public AudioClip DoorCloseSound;
    
            public bool RequireHandleTurnToOpen = false;
    
    
    
            public Transform HandleFollower;
    
            public float DegreesTurned;
    
    
    
            public float DegreesTurnToOpen = 10f;
    
    
    
            public Transform DoorLockTransform;
    
            float initialLockPosition;
    
            HingeJoint hinge;
    
            Rigidbody rigid;
    
            bool playedOpenSound = false;
    
            bool readyToPlayCloseSound = false;
    
            public float AngularVelocitySnapDoor = 0.2f;
    
            void Start() {
    
                hinge = GetComponent<HingeJoint>();
    
                rigid = GetComponent<Rigidbody>();
    
                if(DoorLockTransform) {
    
                    initialLockPosition = DoorLockTransform.transform.localPosition.x;
    
                }
    
            }
    
            public float angle;
    
            public float AngularVelocity = 0.2f;
    
            bool doorLocked = false;
    
            public float lockPos;
    
    
    
            Vector3 currentRotation;
    
            float moveLockAmount, rotateAngles, ratio;
    
            void Update() {
    
                AngularVelocity = rigid.angularVelocity.magnitude;
    
    
    
                currentRotation = transform.localEulerAngles;
    
                angle = Mathf.Floor(currentRotation.y);
    
                if(angle >= 180) {
    
                    angle -= 180;
    
                }
    
                else {
    
                    angle = 180 - angle;
    
                }
    
                if (angle > 10) {
    
                    if(!playedOpenSound) {
    
                        VRUtils.Instance.PlaySpatialClipAt(DoorOpenSound, transform.position, 1f, 1f);
    
                        playedOpenSound = true;
    
                    }
    
                }
    
                if(angle > 30) {
    
                    readyToPlayCloseSound = true;
    
                }
    
                if(angle < 2 && playedOpenSound) {
    
                    playedOpenSound = false;
    
                }
    
                if (angle < 1 && AngularVelocity <= AngularVelocitySnapDoor) {
    
                    rigid.angularVelocity = Vector3.zero;
    
                }
    
                if (readyToPlayCloseSound && angle < 2) {
    
                    VRUtils.Instance.PlaySpatialClipAt(DoorCloseSound, transform.position, 1f, 1f);
    
                    readyToPlayCloseSound = false;
    
                }
    
                if (HandleFollower) {
    
                    DegreesTurned = Mathf.Abs(HandleFollower.localEulerAngles.y - 270);
    
                }
    
                if(DoorLockTransform) {
    
                    moveLockAmount = 0.025f;
    
                    rotateAngles = 55;
    
                    ratio = rotateAngles / (rotateAngles - Mathf.Clamp(DegreesTurned, 0, rotateAngles));
    
                    lockPos =  initialLockPosition - (ratio * moveLockAmount) + moveLockAmount;
    
                    lockPos = Mathf.Clamp(lockPos, initialLockPosition - moveLockAmount, initialLockPosition);
    
                    DoorLockTransform.transform.localPosition = new Vector3(lockPos, DoorLockTransform.transform.localPosition.y, DoorLockTransform.transform.localPosition.z);
    
                }
    
                if(RequireHandleTurnToOpen) {
    
                    doorLocked = DegreesTurned < DegreesTurnToOpen;
    
                }
    
                if(angle < 0.02f && doorLocked) {
    
                    if (rigid.collisionDetectionMode == CollisionDetectionMode.Continuous || rigid.collisionDetectionMode == CollisionDetectionMode.ContinuousDynamic) {
    
                        rigid.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
    
                    }
    
                    rigid.isKinematic = true;
    
                }
    
                else {
    
                    if (rigid.collisionDetectionMode == CollisionDetectionMode.ContinuousSpeculative) {
    
                        rigid.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
    
                    }
    
                    rigid.isKinematic = false;
    
                }
    
    
    
            }
    
        }
    
    }
    
    

    PlayerClimbing

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    namespace BNG {
    
        public class PlayerClimbing : MonoBehaviour {
    
            public Transform LeftControllerTransform;
    
            public Transform RightControllerTransform;
    
            public float ClimbingCapsuleHeight = 0.5f;
    
            public float ClimbingCapsuleCenter = -0.25f;
    
            public bool ApplyHapticsOnGrab = true;
    
            public float VibrateFrequency = 0.3f;
    
            public float VibrateAmplitude = 0.1f;
    
            public float VibrateDuration = 0.1f;
    
            List<Grabber> climbers;
    
            bool wasGrippingClimbable;
    
            CharacterController characterController;
    
            SmoothLocomotion smoothLocomotion;
    
            PlayerGravity playerGravity;
    
            [Header("Shown for Debug : ")]
    
    
    
            public bool GrippingClimbable = false;
    
            private Vector3 moveDirection = Vector3.zero;
    
            Vector3 previousLeftControllerPosition;
    
            Vector3 previousRightControllerPosition;
    
            Vector3 controllerMoveAmount;
    
            public void Start() {
    
                climbers = new List<Grabber>();
    
                characterController = GetComponentInChildren<CharacterController>();
    
                smoothLocomotion = GetComponentInChildren<SmoothLocomotion>();
    
                playerGravity = GetComponentInChildren<PlayerGravity>();
    
            }
    
            public void LateUpdate() {
    
                checkClimbing();
    
                if (LeftControllerTransform != null) {
    
                    previousLeftControllerPosition = LeftControllerTransform.position;
    
                }
    
                if (RightControllerTransform != null) {
    
                    previousRightControllerPosition = RightControllerTransform.position;
    
                }
    
            }
    
            public virtual void AddClimber(Climbable climbable, Grabber grab) {
    
                if (climbers == null) {
    
                    climbers = new List<Grabber>();
    
                }
    
                if (!climbers.Contains(grab)) {
    
                    if (grab.DummyTransform == null) {
    
                        GameObject go = new GameObject();
    
                        go.transform.name = "DummyTransform";
    
                        go.transform.parent = grab.transform;
    
                        go.transform.position = grab.transform.position;
    
                        go.transform.localEulerAngles = Vector3.zero;
    
                        grab.DummyTransform = go.transform;
    
                    }
    
                    grab.DummyTransform.parent = climbable.transform;
    
    
    
                    grab.PreviousPosition = grab.DummyTransform.position;
    
                    if(ApplyHapticsOnGrab) {
    
                        InputBridge.Instance.VibrateController(VibrateFrequency, VibrateAmplitude, VibrateDuration, grab.HandSide);
    
                    }
    
                    climbers.Add(grab);
    
                }
    
            }
    
            public virtual void RemoveClimber(Grabber grab) {
    
                if (climbers.Contains(grab)) {
    
                    grab.DummyTransform.parent = grab.transform;
    
                    grab.DummyTransform.localPosition = Vector3.zero;
    
                    climbers.Remove(grab);
    
                }
    
            }
    
            public virtual bool GrippingAtLeastOneClimbable() {
    
                if (climbers != null && climbers.Count > 0) {
    
                    for (int x = 0; x < climbers.Count; x++) {
    
                        if (climbers[x] != null && climbers[x].HoldingItem) {
    
                            return true;
    
                        }
    
                    }
    
                    climbers = new List<Grabber>();
    
                }
    
                return false;
    
            }
    
            protected virtual void checkClimbing() {
    
                GrippingClimbable = GrippingAtLeastOneClimbable();
    
                if (GrippingClimbable && !wasGrippingClimbable) {
    
                    onGrabbedClimbable();
    
                }
    
                if (wasGrippingClimbable && !GrippingClimbable) {
    
                    onReleasedClimbable();
    
                }
    
                if (GrippingClimbable) {
    
                    moveDirection = Vector3.zero;
    
                    int count = 0;
    
                    float length = climbers.Count;
    
                    for (int i = 0; i < length; i++) {
    
                        Grabber climber = climbers[i];
    
                        if (climber != null && climber.HoldingItem) {
    
                            if (climber.HandSide == ControllerHand.Left) {
    
                                controllerMoveAmount = previousLeftControllerPosition - LeftControllerTransform.position;
    
                            }
    
                            else {
    
                                controllerMoveAmount = previousRightControllerPosition - RightControllerTransform.position;
    
                            }
    
                            if (count == length - 1) {
    
                                moveDirection = controllerMoveAmount;
    
                                moveDirection -= climber.PreviousPosition - climber.DummyTransform.position; ;
    
                            }
    
                            count++;
    
                        }
    
                    }
    
                    if (smoothLocomotion) {
    
                        if(smoothLocomotion.ControllerType == PlayerControllerType.CharacterController) {
    
                            smoothLocomotion.MoveCharacter(moveDirection);
    
                        }
    
                        else if(smoothLocomotion.ControllerType == PlayerControllerType.Rigidbody) {
    
                            smoothLocomotion.MoveRigidCharacter(moveDirection);
    
                            // Rigidbody rigid = smoothLocomotion.GetComponent<Rigidbody>();
    
                            // rigid.velocity = Vector3.MoveTowards(rigid.velocity, (moveDirection * 5000f) * Time.fixedDeltaTime, 1f);
    
                        }
    
                    }
    
                    else if(characterController) {
    
                        characterController.Move(moveDirection);
    
                    }
    
                }
    
                for (int x = 0; x < climbers.Count; x++) {
    
                    Grabber climber = climbers[x];
    
                    if (climber != null && climber.HoldingItem) {
    
                        if (climber.DummyTransform != null) {
    
                            climber.PreviousPosition = climber.DummyTransform.position;
    
                        }
    
                        else {
    
                            climber.PreviousPosition = climber.transform.position;
    
                        }
    
                    }
    
                }
    
                wasGrippingClimbable = GrippingClimbable;
    
            }
    
            void onGrabbedClimbable() {
    
    
    
                if (smoothLocomotion) {
    
                    smoothLocomotion.DisableMovement();
    
                }
    
                if (playerGravity) {
    
                    playerGravity.ToggleGravity(false);
    
                }
    
            }
    
            void onReleasedClimbable() {
    
                if (smoothLocomotion) {
    
                    smoothLocomotion.EnableMovement();
    
                }
    
                if (playerGravity) {
    
                    playerGravity.ToggleGravity(true);
    
                }
    
            }
    
        }
    
    }
    
    

    GunShot

    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using UnityEngine;
    
    namespace BNG {
    
        public class GrappleShot : GrabbableEvents {
    
            public float MaxRange = 100f;
    
            public float GrappleReelForce = 0.5f;
    
            public float MinReelDistance = 0.25f;
    
            public LayerMask GrappleLayers;
    
            public Transform MuzzleTransform;
    
            public Transform HitTargetPrefab;
    
            public LineRenderer GrappleLine;
    
            public LineRenderer HelperLine;
    
            public AudioClip GrappleShotSound;
    
            bool grappling = false;
    
            bool wasGrappling = false;
    
            CharacterController characterController;
    
            SmoothLocomotion smoothLocomotion;
    
            PlayerGravity playerGravity;
    
            PlayerClimbing playerClimbing;
    
            AudioSource audioSource;
    
            public float currentGrappleDistance = 0;
    
            bool validTargetFound = false;
    
    
    
            bool isDynamic = false;
    
            Rigidbody grappleTargetRigid;
    
            Collider grappleTargetCollider;
    
            Transform grappleTargetParent;
    
            bool requireRelease = false;
    
            bool climbing = false;
    
    
    
            public Climbable ClimbHelper;
    
    
    
            void Start() {
    
                GameObject player = GameObject.FindGameObjectWithTag("Player");
    
                if (player) {
    
                    characterController = player.GetComponentInChildren<CharacterController>();
    
                    smoothLocomotion = player.GetComponentInChildren<SmoothLocomotion>();
    
                    playerGravity = player.GetComponentInChildren<PlayerGravity>();
    
                    playerClimbing = player.GetComponentInChildren<PlayerClimbing>();
    
                }
    
                else {
    
                    Debug.Log("No player object found.");
    
                }
    
                audioSource = GetComponent<AudioSource>();
    
            }     
    
            private void LateUpdate() {
    
                if (!grappling && grab.BeingHeld && !requireRelease) {
    
                    drawGrappleHelper();
    
                }
    
                else {
    
                    hideGrappleHelper();
    
                }
    
                if (grappling && validTargetFound && grab.BeingHeld) {
    
                    drawGrappleLine();
    
                }
    
                else {
    
                    hideGrappleLine();
    
                }
    
            }
    
            public override void OnTrigger(float triggerValue) {
    
                updateGrappleDistance();
    
    
    
                if (triggerValue >= 0.25f) {
    
                    if (grappling) {
    
                        reelInGrapple(triggerValue);
    
                    }
    
                    else {
    
                        shootGrapple();
    
                    }
    
                }
    
                else {
    
                    grappling = false;
    
                    requireRelease = false;                           
    
                }
    
    
    
                if(!grappling && wasGrappling) {
    
                    onReleaseGrapple();
    
                }
    
                base.OnTrigger(triggerValue);
    
            }
    
            void updateGrappleDistance() {
    
    
    
                if (grappling) {
    
                    currentGrappleDistance = Vector3.Distance(MuzzleTransform.position, HitTargetPrefab.position);
    
                }
    
                else {
    
                    currentGrappleDistance = 0;
    
                }
    
            }
    
            public override void OnGrab(Grabber grabber) {
    
                base.OnGrab(grabber);
    
            }
    
            public override void OnRelease() {
    
                onReleaseGrapple();
    
                base.OnRelease();
    
            }
    
    
    
            void onReleaseGrapple() {
    
                changeGravity(true);
    
                if(grappleTargetRigid && isDynamic) {
    
                    grappleTargetRigid.useGravity = true;
    
                    grappleTargetRigid.isKinematic = false;
    
                    grappleTargetRigid.transform.parent = grappleTargetParent;
    
    
    
                    if(grappleTargetRigid.GetComponent<Grabbable>()) {
    
                        grappleTargetRigid.GetComponent<Grabbable>().ResetParent();
    
                    }
    
                }
    
    
    
                ClimbHelper.transform.localPosition = Vector3.zero;
    
                playerClimbing.RemoveClimber(thisGrabber);
    
                climbing = false;
    
                grappling = false;
    
                validTargetFound = false;
    
                isDynamic = false;
    
                wasGrappling = false;
    
            }
    
    
    
            void drawGrappleHelper() {
    
                if (HitTargetPrefab) {
    
                    RaycastHit hit;
    
                    if (Physics.Raycast(MuzzleTransform.position, MuzzleTransform.forward, out hit, MaxRange, GrappleLayers, QueryTriggerInteraction.Ignore)) {
    
    
    
                        if (hit.transform.name.StartsWith("Grapple")) {
    
                            hideGrappleHelper();
    
                            validTargetFound = false;
    
                            isDynamic = false;
    
                            return;
    
                        }
    
                        showGrappleHelper(hit.point, Quaternion.FromToRotation(Vector3.forward, hit.normal));
    
                        grappleTargetRigid = hit.collider.GetComponent<Rigidbody>();
    
                        grappleTargetCollider = hit.collider;
    
                        isDynamic = grappleTargetRigid != null && !grappleTargetRigid.isKinematic && grappleTargetRigid.useGravity;
    
    
    
                        bool isUniformVector = hit.collider.transform.localScale.x == hit.collider.transform.localScale.y;
    
                        if (isUniformVector || isDynamic) {
    
                            HitTargetPrefab.parent = null;
    
                            HitTargetPrefab.localScale = Vector3.one;
    
                            HitTargetPrefab.transform.parent = hit.collider.transform;
    
    
    
                        }
    
                        else {
    
                            HitTargetPrefab.parent = null;
    
                            HitTargetPrefab.localScale = Vector3.one;
    
                        }
    
                        validTargetFound = true;
    
                        if(isDynamic) {
    
                            grappleTargetParent = grappleTargetRigid.transform.parent;
    
                        }
    
                        else {
    
                            grappleTargetParent = null;
    
                        }
    
                    }
    
                    else {
    
                        hideGrappleHelper();
    
                        validTargetFound = false;
    
                        isDynamic = false;
    
                    }
    
                }
    
            }
    
            void drawGrappleLine() {
    
                GrappleLine.gameObject.SetActive(true);
    
                GrappleLine.SetPosition(0, MuzzleTransform.position);
    
                GrappleLine.SetPosition(1, HitTargetPrefab.position);
    
            }
    
            void hideGrappleLine() {           
    
                if (GrappleLine && GrappleLine.gameObject.activeSelf) {
    
                    GrappleLine.gameObject.SetActive(false);
    
                }
    
            }
    
            void showGrappleHelper(Vector3 pos, Quaternion rot) {
    
                HitTargetPrefab.gameObject.SetActive(true);
    
                HitTargetPrefab.position = pos;
    
                HitTargetPrefab.rotation = rot;
    
                HitTargetPrefab.localScale = Vector3.one;
    
                if (HelperLine) {
    
                    HelperLine.gameObject.SetActive(true);
    
                    HelperLine.SetPosition(0, MuzzleTransform.position);
    
                    HelperLine.SetPosition(1, pos);
    
                }
    
            }
    
            void hideGrappleHelper() {
    
                if(HitTargetPrefab && HitTargetPrefab.gameObject.activeSelf) {
    
                    HitTargetPrefab.gameObject.SetActive(false);
    
                }
    
                if (HelperLine && HelperLine.gameObject.activeSelf) {
    
                    HelperLine.gameObject.SetActive(false);
    
                }
    
            }
    
            void reelInGrapple(float triggerValue) {
    
    
    
                if(validTargetFound && grappleTargetCollider != null && !grappleTargetCollider.enabled) {
    
                    dropGrapple();
    
                    return;
    
                }
    
                if(validTargetFound && currentGrappleDistance > MinReelDistance) {
    
    
    
    
    
                    if(isDynamic) {
    
                        grappleTargetRigid.isKinematic = false;
    
                        grappleTargetRigid.transform.parent = grappleTargetParent;
    
                        grappleTargetRigid.useGravity = false;
    
                        grappleTargetRigid.AddForce((MuzzleTransform.position - grappleTargetRigid.transform.position) * 0.1f, ForceMode.VelocityChange);
    
    
    
    
    
                    }
    
    
    
                    else {
    
                        Vector3 moveDirection = (HitTargetPrefab.position - MuzzleTransform.position) * GrappleReelForce;
    
    
    
                        changeGravity(false);
    
    
    
                        if(smoothLocomotion) {
    
                            smoothLocomotion.MoveCharacter(moveDirection * Time.deltaTime * triggerValue);
    
                        }
    
    
    
                        else if(characterController) {
    
                            characterController.Move(moveDirection * Time.deltaTime * triggerValue);
    
                        }
    
                    }
    
                }
    
                else if(validTargetFound && currentGrappleDistance <= MinReelDistance) {
    
                    if (isDynamic) {
    
                        //grappleTargetRigid.useGravity = true;
    
                        grappleTargetRigid.velocity = Vector3.zero;
    
                        grappleTargetRigid.isKinematic = true;
    
                        grappleTargetRigid.transform.parent = transform;
    
                    }
    
                    if(!climbing && !isDynamic) {
    
    
    
                        ClimbHelper.transform.localPosition = Vector3.zero;
    
                        playerClimbing.AddClimber(ClimbHelper, thisGrabber);
    
                        climbing = true;
    
                    }
    
    
    
                }
    
            }
    
    
    
            void shootGrapple() {
    
    
    
                if(validTargetFound) {
    
    
    
                    if(GrappleShotSound && audioSource) {
    
                        audioSource.clip = GrappleShotSound;
    
                        audioSource.pitch = Time.timeScale;
    
                        audioSource.Play();
    
                    }
    
                    grappling = true;
    
                    wasGrappling = true;
    
                    requireRelease = true;
    
                }
    
            }
    
            void dropGrapple() {
    
                grappling = false;
    
                validTargetFound = false;
    
                isDynamic = false;
    
                wasGrappling = false;
    
            }
    
            void changeGravity(bool gravityOn) {
    
                if(playerGravity) {
    
                    playerGravity.ToggleGravity(gravityOn);
    
                }
    
            }
    
        }
    
    }
    
    

    三、效果展示

    抓取 UI 触发器 动作同步 方向盘 镜子与白板 开门 攀爬 射击 射箭

    相关文章

      网友评论

          本文标题:OpenXR开发实战项目之VR Interaction Fram

          本文链接:https://www.haomeiwen.com/subject/eftiyrtx.html