OpenXR开发实战项目之VR Interaction Fram

2022-05-03  本文已影响0人  TonyWan_AR

一、框架视图

二、关键代码

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 触发器 动作同步 方向盘 镜子与白板 开门 攀爬 射击 射箭
上一篇下一篇

猜你喜欢

热点阅读