Replace UltimateXR with HurricaneVR
This commit is contained in:
74
Assets/HurricaneVR/Framework/Scripts/Weapons/Bow/HVRArrow.cs
Normal file
74
Assets/HurricaneVR/Framework/Scripts/Weapons/Bow/HVRArrow.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Bow
|
||||
{
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
[RequireComponent(typeof(HVRGrabbable))]
|
||||
public class HVRArrow : MonoBehaviour
|
||||
{
|
||||
public Transform Notch;
|
||||
public Vector3 NotchPointLocal { get; private set; } = Vector3.zero;
|
||||
|
||||
public Rigidbody Rigidbody { get; set; }
|
||||
|
||||
public HVRGrabbable Grabbable { get; private set; }
|
||||
public HVRArrowPassthrough ForwardGrabbable { get; private set; }
|
||||
|
||||
public bool Flying { get; set; }
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (Notch)
|
||||
{
|
||||
NotchPointLocal = Notch.localPosition;
|
||||
}
|
||||
|
||||
Rigidbody = this.GetRigidbody();
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
Grabbable.Grabbed.AddListener(OnGrabbed);
|
||||
|
||||
ForwardGrabbable = GetComponentInChildren<HVRArrowPassthrough>();
|
||||
}
|
||||
|
||||
public void EnableForwardGrabbable()
|
||||
{
|
||||
if(ForwardGrabbable)
|
||||
ForwardGrabbable.enabled = true;
|
||||
}
|
||||
|
||||
public void DisableForwardGrabbable()
|
||||
{
|
||||
if (ForwardGrabbable)
|
||||
ForwardGrabbable.enabled = false;
|
||||
}
|
||||
|
||||
private void OnGrabbed(HVRGrabberBase arg0, HVRGrabbable arg1)
|
||||
{
|
||||
Flying = false;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Flying)
|
||||
{
|
||||
transform.forward = Vector3.Slerp(transform.forward, Rigidbody.velocity.normalized, Time.deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void FixedUpdate()
|
||||
{
|
||||
if (Rigidbody.velocity.sqrMagnitude < 1f)
|
||||
{
|
||||
Flying = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
Flying = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4961525acc8e94846ab15a6ebeed42a8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Bow
|
||||
{
|
||||
[RequireComponent(typeof(HVRPhysicsBow))]
|
||||
public class HVRArrowLoader : MonoBehaviour
|
||||
{
|
||||
public HVRGrabbable NockGrabbable;
|
||||
public GameObject ArrowPrefab;
|
||||
|
||||
public HVRPhysicsBow bow { get; private set; }
|
||||
|
||||
public void Start()
|
||||
{
|
||||
bow = GetComponent<HVRPhysicsBow>();
|
||||
|
||||
if (NockGrabbable)
|
||||
{
|
||||
NockGrabbable.HandGrabbed.AddListener(OnStringGrabbed);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStringGrabbed(HVRHandGrabber hand, HVRGrabbable arg1)
|
||||
{
|
||||
if (!bow.ArrowNocked && ArrowPrefab)
|
||||
{
|
||||
var go = Instantiate(ArrowPrefab);
|
||||
var arrow = go.GetComponent<HVRArrow>();
|
||||
bow.NockArrow(arrow);
|
||||
hand.DisableHandCollision(arrow.Grabbable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4daa695d62072d64f89a844cb8274fda
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using Assets.HurricaneVR.Framework.Shared.Utilities;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Bow
|
||||
{
|
||||
public class HVRArrowPassthrough : HVRGrabbable
|
||||
{
|
||||
public HVRGrabbable Arrow;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
if (!Arrow && transform.parent)
|
||||
{
|
||||
Arrow = transform.parent.GetComponentInParent<HVRGrabbable>();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnGrabbed(HVRGrabberBase grabber)
|
||||
{
|
||||
grabber.ForceRelease();
|
||||
if (Arrow)
|
||||
{
|
||||
grabber.AllowGrabbing = false;
|
||||
this.ExecuteNextUpdate(() =>
|
||||
{
|
||||
grabber.TryGrab(Arrow, true);
|
||||
grabber.AllowGrabbing = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c20151e078b7ac4a9673ee89501f652
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Bow
|
||||
{
|
||||
[RequireComponent(typeof(HVRPhysicsBow))]
|
||||
public class HVRBowAnimator : MonoBehaviour
|
||||
{
|
||||
public Animator Animator;
|
||||
public HVRPhysicsBow Bow { get; private set; }
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Bow = GetComponent<HVRPhysicsBow>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Animator)
|
||||
{
|
||||
|
||||
Animator.enabled = true;
|
||||
Animator.Play(0, 0, Bow.Tension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95ad415173bd87641b0911ab7c483a6a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
456
Assets/HurricaneVR/Framework/Scripts/Weapons/Bow/HVRBowBase.cs
Normal file
456
Assets/HurricaneVR/Framework/Scripts/Weapons/Bow/HVRBowBase.cs
Normal file
@@ -0,0 +1,456 @@
|
||||
using System.Collections;
|
||||
using Assets.HurricaneVR.Framework.Shared.Utilities;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Bow
|
||||
{
|
||||
[RequireComponent(typeof(HVRGrabbable))]
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRBowBase : MonoBehaviour
|
||||
{
|
||||
[Header("Bow String")]
|
||||
public HVRGrabbable NockGrabbable;
|
||||
|
||||
public float StringLimit = .5f;
|
||||
public float StringDropLimit = .6f;
|
||||
|
||||
[Header("Settings")]
|
||||
public HVRBowLimitStyle StringLimitStyle = HVRBowLimitStyle.Limit;
|
||||
|
||||
public float ShootThreshold = .2f;
|
||||
public float Speed = 50f;
|
||||
public AnimationCurve SpeedCurve;
|
||||
public bool ReverseArrowsRests;
|
||||
|
||||
|
||||
[Header("Transforms")]
|
||||
[Tooltip("Arrow Rest When the bow is held with the left hand.")]
|
||||
public Transform LeftRest;
|
||||
|
||||
[Tooltip("Arrow Rest When the bow is held with the right hand.")]
|
||||
public Transform RightRest;
|
||||
|
||||
[Tooltip("Transform for forward vector, uses this transform if not provided.")]
|
||||
public Transform ForwardMarker;
|
||||
|
||||
[Header("Haptics")]
|
||||
public bool StringHaptics = true;
|
||||
|
||||
public bool BowHandHaptics = true;
|
||||
|
||||
[Tooltip("Number of haptic ticks by percent traveled.")]
|
||||
[Range(.02f, 1f)]
|
||||
public float HapticStep = .01f;
|
||||
|
||||
[Tooltip("Vibration strength when pulling the bow.")]
|
||||
[Range(0f, 1f)]
|
||||
public float HapticsMinAmplitude = .1f;
|
||||
|
||||
[Tooltip("Vibration strength when pulling the bow.")]
|
||||
[Range(0f, 1f)]
|
||||
public float HapticsMaxAmplitude = .1f;
|
||||
|
||||
[Tooltip("Vibration frequency when pulling the bow.")]
|
||||
public float HapticsDuration = .01f;
|
||||
|
||||
[Tooltip("Vibration frequency when pulling the bow.")]
|
||||
public float HapticsFrequency = 1f;
|
||||
|
||||
[Header("SFX")]
|
||||
public AudioClip StringClip;
|
||||
|
||||
public float StringMinPitch = 1f;
|
||||
public float StringMaxPitch = 1.25f;
|
||||
|
||||
public AudioClip[] ReleasedSFX;
|
||||
|
||||
|
||||
public Transform Rest { get; protected set; }
|
||||
public float Tension { get; protected set; }
|
||||
|
||||
public Vector3 Forward => transform.InverseTransformDirection(ForwardMarker.forward);
|
||||
public Vector3 WorldForward => ForwardMarker.forward;
|
||||
|
||||
public bool ArrowNocked => Arrow;
|
||||
|
||||
protected HVRArrow Arrow { get; set; }
|
||||
|
||||
public HVRNockingPoint NockSocket { get; private set; }
|
||||
public HVRGrabbable Grabbable { get; private set; }
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
protected HVRHandGrabber NockHand;
|
||||
|
||||
protected HVRHandGrabber BowHand;
|
||||
|
||||
private Vector3 _nockStart;
|
||||
private Vector3 _nockDir;
|
||||
private float _nockDistance;
|
||||
private bool _previousHeld;
|
||||
private float _previousHapticDistance;
|
||||
private float _shootSpeed;
|
||||
private float _previousArrowSleep;
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
if (!ForwardMarker)
|
||||
{
|
||||
ForwardMarker = this.transform;
|
||||
}
|
||||
|
||||
Rest = LeftRest;
|
||||
|
||||
NockSocket = GetComponentInChildren<HVRNockingPoint>();
|
||||
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
Rigidbody = GetComponent<Rigidbody>();
|
||||
|
||||
NockSocket.BeforeHoverEnter.AddListener(BeforeNockHovered);
|
||||
NockSocket.Grabbed.AddListener(OnArrowSocketed);
|
||||
|
||||
Grabbable.Grabbed.AddListener(OnGrabbed);
|
||||
Grabbable.Released.AddListener(OnReleased);
|
||||
Grabbable.HandGrabbed.AddListener(OnHandGrabbed);
|
||||
Grabbable.HandReleased.AddListener(OnHandReleased);
|
||||
Grabbable.Socketed.AddListener(OnBowSocketed);
|
||||
Grabbable.UnSocketed.AddListener(OnBowUnsocketed);
|
||||
|
||||
NockGrabbable.HandGrabbed.AddListener(OnStringGrabbed);
|
||||
NockGrabbable.HandReleased.AddListener(OnStringReleased);
|
||||
|
||||
NockSocket.ParentGrabbable = Grabbable;
|
||||
|
||||
_nockStart = transform.InverseTransformPoint(NockGrabbable.transform.position);
|
||||
|
||||
|
||||
if (SpeedCurve == null)
|
||||
{
|
||||
SpeedCurve = new AnimationCurve();
|
||||
}
|
||||
|
||||
if (SpeedCurve.keys.Length == 0)
|
||||
{
|
||||
SpeedCurve.AddKey(0f, 1f);
|
||||
SpeedCurve.AddKey(1f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
UpdateBow();
|
||||
}
|
||||
|
||||
protected virtual void UpdateBow()
|
||||
{
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
BeforeFixedUpdateBow();
|
||||
FixedUpdateBow();
|
||||
AfterFixedUpdateBow();
|
||||
}
|
||||
|
||||
protected virtual void BeforeFixedUpdateBow()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void AfterFixedUpdateBow()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void FixedUpdateBow()
|
||||
{
|
||||
var nockPosition = transform.InverseTransformPoint(NockGrabbable.transform.position);
|
||||
|
||||
_nockDir = nockPosition - _nockStart;
|
||||
_nockDistance = _nockDir.magnitude;
|
||||
Tension = _nockDistance / StringLimit;
|
||||
Tension = Mathf.Clamp(Tension, 0f, 1f);
|
||||
|
||||
UpdateHaptics(_nockDistance);
|
||||
|
||||
CheckDropArrow();
|
||||
CheckArrowRelease();
|
||||
|
||||
_previousHeld = NockGrabbable.IsBeingHeld;
|
||||
}
|
||||
|
||||
public void NockArrow(HVRArrow arrow)
|
||||
{
|
||||
if (Arrow)
|
||||
return;
|
||||
|
||||
OnArrowNocked(arrow);
|
||||
}
|
||||
|
||||
protected virtual void CheckArrowRelease()
|
||||
{
|
||||
var shootArrow = false;
|
||||
|
||||
if (StringLimitStyle == HVRBowLimitStyle.ShootArrow && _nockDistance > StringLimit)
|
||||
{
|
||||
NockGrabbable.ForceRelease();
|
||||
shootArrow = Arrow;
|
||||
}
|
||||
|
||||
if (!Arrow)
|
||||
return;
|
||||
|
||||
if (!shootArrow && _previousHeld && !NockGrabbable.IsBeingHeld && _nockDistance > ShootThreshold)
|
||||
{
|
||||
shootArrow = true;
|
||||
}
|
||||
|
||||
if (shootArrow)
|
||||
{
|
||||
OnArrowShot();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnArrowShot()
|
||||
{
|
||||
OnArrowRemoved(Arrow);
|
||||
|
||||
_shootSpeed = SpeedCurve.Evaluate(Tension) * Speed;
|
||||
|
||||
PlayReleasedSFX();
|
||||
|
||||
ShootArrow(Arrow.transform.forward);
|
||||
}
|
||||
|
||||
protected virtual void ShootArrow(Vector3 direction)
|
||||
{
|
||||
Arrow.Rigidbody.sleepThreshold = _previousArrowSleep;
|
||||
Arrow.Grabbable.CanBeGrabbed = true;
|
||||
Arrow.Rigidbody.velocity = direction * _shootSpeed;
|
||||
Arrow.Rigidbody.angularVelocity = Vector3.zero;
|
||||
Arrow.Flying = true;
|
||||
Arrow = null;
|
||||
}
|
||||
|
||||
protected virtual void CheckDropArrow()
|
||||
{
|
||||
if (StringLimitStyle != HVRBowLimitStyle.DropArrow || !Arrow)
|
||||
return;
|
||||
|
||||
if (_nockDistance > StringDropLimit)
|
||||
{
|
||||
NockGrabbable.ForceRelease();
|
||||
OnArrowDropped();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateHaptics(float nockDistance)
|
||||
{
|
||||
if (nockDistance > _previousHapticDistance + HapticStep ||
|
||||
nockDistance < _previousHapticDistance - HapticStep)
|
||||
{
|
||||
var amplitude = nockDistance.Remap(0, StringLimit, HapticsMinAmplitude, HapticsMaxAmplitude);
|
||||
|
||||
if (StringHaptics && NockGrabbable.HandGrabbers.Count > 0)
|
||||
NockGrabbable.HandGrabbers[0].Controller.Vibrate(amplitude, HapticsDuration, HapticsFrequency);
|
||||
|
||||
if (BowHandHaptics && Grabbable.HandGrabbers.Count > 0)
|
||||
Grabbable.HandGrabbers[0].Controller.Vibrate(amplitude, HapticsDuration, HapticsFrequency);
|
||||
|
||||
PlayStringSFX(nockDistance);
|
||||
|
||||
|
||||
_previousHapticDistance = nockDistance;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void PlayStringSFX(float nockDistance)
|
||||
{
|
||||
var pitch = nockDistance.Remap(0, StringLimit, StringMinPitch, StringMaxPitch);
|
||||
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(StringClip, NockGrabbable.transform.position, pitch, 1f);
|
||||
}
|
||||
|
||||
protected virtual void PlayReleasedSFX()
|
||||
{
|
||||
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(ReleasedSFX.GetRandom(), NockGrabbable.transform.position);
|
||||
}
|
||||
|
||||
protected virtual void OnGrabbed(HVRGrabberBase arg0, HVRGrabbable arg1)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnReleased(HVRGrabberBase arg0, HVRGrabbable arg1)
|
||||
{
|
||||
}
|
||||
|
||||
private void BeforeNockHovered(HVRGrabberBase grabber, HVRGrabbable grabbable)
|
||||
{
|
||||
NockHand = grabbable.PrimaryGrabber as HVRHandGrabber;
|
||||
}
|
||||
|
||||
protected virtual void OnArrowSocketed(HVRGrabberBase arg0, HVRGrabbable grabbable)
|
||||
{
|
||||
var arrow = grabbable.transform.GetComponent<HVRArrow>();
|
||||
if (!arrow)
|
||||
{
|
||||
NockHand = null;
|
||||
Debug.LogWarning($"{grabbable.name} missing HVRArrow component.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OnArrowNocked(arrow);
|
||||
}
|
||||
|
||||
protected virtual void OnArrowNocked(HVRArrow arrow)
|
||||
{
|
||||
_previousArrowSleep = arrow.Rigidbody.sleepThreshold;
|
||||
|
||||
arrow.transform.rotation = Quaternion.LookRotation(WorldForward, NockSocket.transform.up);
|
||||
arrow.transform.position = NockSocket.transform.position;
|
||||
|
||||
|
||||
var grabbable = arrow.Grabbable;
|
||||
//grabbable.ForceRelease();
|
||||
grabbable.CanBeGrabbed = false;
|
||||
grabbable.Rigidbody.sleepThreshold = 0f;
|
||||
grabbable.Grabbed.AddListener(OnNockedArrowGrabbed);
|
||||
|
||||
UpdateBowHandCollision(BowHand, grabbable, false);
|
||||
|
||||
NockSocket.AllowGrabbing = false;
|
||||
Arrow = arrow;
|
||||
|
||||
Grabbable.IgnoreCollision(grabbable);
|
||||
|
||||
if (NockHand)
|
||||
{
|
||||
NockHand.DisableHandCollision(Arrow.Grabbable);
|
||||
NockHand.TryGrab(NockGrabbable, true);
|
||||
NockHand = null;
|
||||
}
|
||||
|
||||
arrow.EnableForwardGrabbable();
|
||||
}
|
||||
|
||||
protected virtual void OnNockedArrowGrabbed(HVRGrabberBase arg0, HVRGrabbable arg1)
|
||||
{
|
||||
OnArrowDropped();
|
||||
}
|
||||
|
||||
protected virtual void OnHandGrabbed(HVRHandGrabber hand, HVRGrabbable bow)
|
||||
{
|
||||
BowHand = hand;
|
||||
|
||||
if (Arrow)
|
||||
{
|
||||
UpdateBowHandCollision(hand, Arrow.Grabbable, false);
|
||||
}
|
||||
|
||||
if (hand.HandSide == HVRHandSide.Left && !ReverseArrowsRests)
|
||||
{
|
||||
Rest = LeftRest;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rest = RightRest;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnHandReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
if (Arrow)
|
||||
{
|
||||
StartCoroutine(EnableBowHandCollisionRoutine(arg0, Arrow.Grabbable));
|
||||
}
|
||||
|
||||
BowHand = null;
|
||||
}
|
||||
|
||||
protected virtual void OnStringReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnStringGrabbed(HVRHandGrabber hand, HVRGrabbable nock)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnBowSocketed(HVRSocket arg0, HVRGrabbable arg1)
|
||||
{
|
||||
if (Arrow)
|
||||
{
|
||||
OnArrowDropped();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnBowUnsocketed(HVRSocket arg0, HVRGrabbable arg1)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnArrowDropped()
|
||||
{
|
||||
OnArrowRemoved(Arrow);
|
||||
|
||||
Arrow.Rigidbody.sleepThreshold = _previousArrowSleep;
|
||||
Arrow.Grabbable.CanBeGrabbed = true;
|
||||
|
||||
Arrow = null;
|
||||
}
|
||||
|
||||
protected virtual void OnArrowRemoved(HVRArrow arrow)
|
||||
{
|
||||
this.ExecuteAfterSeconds(() => NockSocket.AllowGrabbing = true, .25f);
|
||||
|
||||
StartCoroutine(EnableBowHandCollisionRoutine(BowHand, arrow.Grabbable));
|
||||
|
||||
arrow.Grabbable.Grabbed.RemoveListener(OnNockedArrowGrabbed);
|
||||
|
||||
arrow.DisableForwardGrabbable();
|
||||
}
|
||||
|
||||
protected void UpdateBowHandCollision(HVRHandGrabber hand, HVRGrabbable arrow, bool enable)
|
||||
{
|
||||
if (hand && arrow)
|
||||
{
|
||||
hand.UpdateCollision(arrow, enable);
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerator EnableBowHandCollisionRoutine(HVRHandGrabber hand, HVRGrabbable arrow)
|
||||
{
|
||||
if (!hand || !arrow)
|
||||
yield break;
|
||||
yield return new WaitForSeconds(1f);
|
||||
if (BowHand && BowHand == hand || !arrow)
|
||||
yield break;
|
||||
UpdateBowHandCollision(hand, arrow, true);
|
||||
Grabbable.IgnoreCollision(arrow, false);
|
||||
}
|
||||
|
||||
public void OnDrawGizmosSelected()
|
||||
{
|
||||
if (NockGrabbable && Rest)
|
||||
{
|
||||
var forward = Rest.transform.position - NockGrabbable.transform.position;
|
||||
Gizmos.color = Color.green;
|
||||
Gizmos.DrawSphere(NockGrabbable.transform.position - forward.normalized * ShootThreshold, .02f);
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawSphere(NockGrabbable.transform.position - forward.normalized * StringLimit, .02f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum HVRBowLimitStyle
|
||||
{
|
||||
Limit,
|
||||
ShootArrow,
|
||||
DropArrow
|
||||
}
|
||||
|
||||
public class HVRBowEvent : UnityEvent<HVRPhysicsBow>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e9a76a97fc7a0f4a977816fe4d34add
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Bow
|
||||
{
|
||||
public class HVRNockingPoint : HVRSocket
|
||||
{
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
ScaleGrabbable = false;
|
||||
GrabbableMustBeHeld = true;
|
||||
GrabsFromHand = true;
|
||||
CanRemoveGrabbable = false;
|
||||
ParentDisablesGrab = true;
|
||||
}
|
||||
|
||||
protected override void OnGrabbed(HVRGrabArgs args)
|
||||
{
|
||||
//Debug.Log($"nocked");
|
||||
args.Cancel = true;
|
||||
Grabbed.Invoke(this, args.Grabbable);
|
||||
//ForceRelease();
|
||||
}
|
||||
|
||||
protected override void OnReleased(HVRGrabbable grabbable)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnHoverEnter(HVRGrabbable grabbable)
|
||||
{
|
||||
if (grabbable.LeftHandGrabber) grabbable.LeftHandGrabber.IgnoreNextCollisionCheck = true;
|
||||
if (grabbable.RightHandGrabber) grabbable.RightHandGrabber.IgnoreNextCollisionCheck = true;
|
||||
base.OnHoverEnter(grabbable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2438268ac55dd3544a75a36f11afc5a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,228 @@
|
||||
using Assets.HurricaneVR.Framework.Shared.Utilities;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Bow
|
||||
{
|
||||
[RequireComponent(typeof(HVRGrabbable))]
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRPhysicsBow : HVRBowBase
|
||||
{
|
||||
[Header("Physics Bow Settings")]
|
||||
public float StringSpring = 10000f;
|
||||
public float StringHeldSpring = 100f;
|
||||
|
||||
[Tooltip("If true the nock joint will be freed on the forward axis which will allow the hand to rotate while holding the nock")]
|
||||
public bool CanNockRotate;
|
||||
|
||||
|
||||
public Rigidbody NockRigidbody => NockGrabbable.Rigidbody;
|
||||
|
||||
private ConfigurableJoint _stringJoint;
|
||||
private ConfigurableJoint _stringLimitJoint;
|
||||
private ConfigurableJoint _nockJoint;
|
||||
private ConfigurableJoint _restJoint;
|
||||
private Vector3 _nockPosition;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
SetupStringJoint();
|
||||
_nockPosition = NockGrabbable.transform.localPosition;
|
||||
}
|
||||
|
||||
protected override void AfterFixedUpdateBow()
|
||||
{
|
||||
base.AfterFixedUpdateBow();
|
||||
UpdateRestAnchor();
|
||||
}
|
||||
|
||||
private void UpdateRestAnchor()
|
||||
{
|
||||
if (_restJoint && Arrow)
|
||||
{
|
||||
var anchor = Arrow.transform.InverseTransformPoint(Rest.transform.position);
|
||||
anchor.Scale(Forward);
|
||||
_restJoint.connectedAnchor = anchor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void OnStringReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
_stringJoint.SetXDrive(StringSpring, 0f, StringSpring);
|
||||
}
|
||||
|
||||
protected override void OnStringGrabbed(HVRHandGrabber hand, HVRGrabbable nock)
|
||||
{
|
||||
if (Arrow)
|
||||
{
|
||||
hand.DisableHandCollision(Arrow.Grabbable);
|
||||
}
|
||||
|
||||
_stringJoint.SetXDrive(StringHeldSpring, 0, StringHeldSpring);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void OnArrowNocked(HVRArrow arrow)
|
||||
{
|
||||
base.OnArrowNocked(arrow);
|
||||
|
||||
SetupNockJoint(arrow);
|
||||
SetupRestJoint(arrow);
|
||||
}
|
||||
|
||||
protected override void OnBowSocketed(HVRSocket arg0, HVRGrabbable arg1)
|
||||
{
|
||||
base.OnBowSocketed(arg0, arg1);
|
||||
NockRigidbody.SetKinematic();
|
||||
NockGrabbable.transform.localPosition = _nockPosition;
|
||||
}
|
||||
|
||||
protected override void OnBowUnsocketed(HVRSocket arg0, HVRGrabbable arg1)
|
||||
{
|
||||
base.OnBowUnsocketed(arg0, arg1);
|
||||
NockRigidbody.isKinematic = false;
|
||||
NockRigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;
|
||||
}
|
||||
|
||||
|
||||
protected override void OnArrowRemoved(HVRArrow arrow)
|
||||
{
|
||||
base.OnArrowRemoved(arrow);
|
||||
|
||||
if (_nockJoint)
|
||||
{
|
||||
Destroy(_nockJoint);
|
||||
}
|
||||
|
||||
if (_restJoint)
|
||||
{
|
||||
Destroy(_restJoint);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ShootArrow(Vector3 direction)
|
||||
{
|
||||
var pos = Arrow.transform.position;
|
||||
var rot = Arrow.transform.rotation;
|
||||
|
||||
//the joints are preventing the arrow from shooting in the same frame perhaps???
|
||||
this.ExecuteAfterFixedUpdate(() =>
|
||||
{
|
||||
Arrow.transform.SetPositionAndRotation(pos, rot);
|
||||
base.ShootArrow(direction);
|
||||
});
|
||||
}
|
||||
|
||||
private void SetupStringJoint()
|
||||
{
|
||||
_stringJoint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
|
||||
var axis = Forward;
|
||||
|
||||
_stringJoint.axis = axis;
|
||||
_stringJoint.secondaryAxis = axis.OrthogonalVector();
|
||||
|
||||
_stringJoint.LimitXMotion();
|
||||
_stringJoint.LockYMotion();
|
||||
_stringJoint.LockZMotion();
|
||||
|
||||
if (CanNockRotate)
|
||||
{
|
||||
_stringJoint.LockAngularYMotion();
|
||||
_stringJoint.LockAngularZMotion();
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringJoint.LockAllAngularMotion();
|
||||
}
|
||||
|
||||
_stringJoint.SetXDrive(StringSpring, 0, StringSpring);
|
||||
_stringJoint.anchor = transform.InverseTransformPoint(NockRigidbody.position) - axis * StringLimit;
|
||||
_stringJoint.targetPosition = Vector3.right * StringLimit;
|
||||
_stringJoint.autoConfigureConnectedAnchor = false;
|
||||
_stringJoint.connectedBody = NockRigidbody;
|
||||
_stringJoint.connectedAnchor = Vector3.zero;
|
||||
_stringJoint.projectionMode = JointProjectionMode.PositionAndRotation;
|
||||
_stringJoint.projectionDistance = .001f;
|
||||
|
||||
_stringJoint.linearLimit = new SoftJointLimit()
|
||||
{
|
||||
limit = StringLimit
|
||||
};
|
||||
|
||||
if (StringLimitStyle == HVRBowLimitStyle.Limit)
|
||||
{
|
||||
_stringLimitJoint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
|
||||
_stringLimitJoint.axis = axis;
|
||||
_stringLimitJoint.secondaryAxis = axis.OrthogonalVector();
|
||||
|
||||
_stringLimitJoint.LimitXMotion();
|
||||
_stringLimitJoint.LockYMotion();
|
||||
_stringLimitJoint.LockZMotion();
|
||||
|
||||
if (CanNockRotate)
|
||||
{
|
||||
_stringLimitJoint.LockAngularYMotion();
|
||||
_stringLimitJoint.LockAngularZMotion();
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringLimitJoint.LockAllAngularMotion();
|
||||
}
|
||||
|
||||
_stringLimitJoint.anchor = transform.InverseTransformPoint(NockRigidbody.position);
|
||||
_stringLimitJoint.autoConfigureConnectedAnchor = false;
|
||||
_stringLimitJoint.connectedBody = NockRigidbody;
|
||||
_stringLimitJoint.connectedAnchor = Vector3.zero;
|
||||
_stringLimitJoint.projectionMode = JointProjectionMode.PositionAndRotation;
|
||||
_stringLimitJoint.projectionDistance = .001f;
|
||||
|
||||
_stringLimitJoint.linearLimit = new SoftJointLimit()
|
||||
{
|
||||
limit = StringLimit
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupNockJoint(HVRArrow arrow)
|
||||
{
|
||||
_nockJoint = NockRigidbody.gameObject.AddComponent<ConfigurableJoint>();
|
||||
|
||||
var axis = Forward;
|
||||
_nockJoint.axis = axis;
|
||||
_nockJoint.secondaryAxis = axis.OrthogonalVector();
|
||||
_nockJoint.LockYMotion();
|
||||
_nockJoint.LockZMotion();
|
||||
_nockJoint.LockLinearMotion();
|
||||
_nockJoint.LockAllAngularMotion();
|
||||
_nockJoint.anchor = Vector3.zero;
|
||||
_nockJoint.autoConfigureConnectedAnchor = false;
|
||||
_nockJoint.connectedBody = arrow.Rigidbody;
|
||||
_nockJoint.connectedAnchor = arrow.NotchPointLocal;
|
||||
}
|
||||
|
||||
private void SetupRestJoint(HVRArrow arrow)
|
||||
{
|
||||
_restJoint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
|
||||
var axis = Forward;
|
||||
_restJoint.axis = axis;
|
||||
_restJoint.secondaryAxis = axis.OrthogonalVector();
|
||||
|
||||
_restJoint.LockYMotion();
|
||||
_restJoint.LockZMotion();
|
||||
|
||||
_restJoint.anchor = transform.InverseTransformPoint(Rest.transform.position);
|
||||
_restJoint.autoConfigureConnectedAnchor = false;
|
||||
_restJoint.connectedBody = arrow.Rigidbody;
|
||||
_restJoint.connectedAnchor = arrow.transform.InverseTransformPoint(Rest.transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85b2b482c7b701c4a91db69ec8b0ac1e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user