Replace UltimateXR with HurricaneVR
This commit is contained in:
8
Assets/HurricaneVR/Framework/Scripts/Weapons/Bow.meta
Normal file
8
Assets/HurricaneVR/Framework/Scripts/Weapons/Bow.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83c3bfee872eb894785139b7a23da4f5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
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:
|
||||
8
Assets/HurricaneVR/Framework/Scripts/Weapons/Guns.meta
Normal file
8
Assets/HurricaneVR/Framework/Scripts/Weapons/Guns.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5fea5ebfaa0a0d448962e145ae9a991
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using Assets.HurricaneVR.Framework.Shared.Utilities;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRAutoDropMagazine : HVRSocket
|
||||
{
|
||||
public HVRSocket MagazineSocket;
|
||||
|
||||
|
||||
protected override void OnHoverEnter(HVRGrabbable grabbable)
|
||||
{
|
||||
ForceRelease();
|
||||
if (MagazineSocket && IsValid(grabbable) && grabbable.HandGrabbers.Count > 0)
|
||||
{
|
||||
Debug.Log($"drop");
|
||||
MagazineSocket.ForceRelease();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsValid(HVRGrabbable grabbable)
|
||||
{
|
||||
if (!MagazineSocket || !MagazineSocket.IsGrabbing)
|
||||
return false;
|
||||
|
||||
return MagazineSocket.IsValid(grabbable);
|
||||
}
|
||||
|
||||
public override bool CanGrab(HVRGrabbable grabbable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9329b61191544954aadf4fa05841e222
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRAutomaticGun : HVRGunBase
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f9db1f9e84328a44ae9e19e161049a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using HurricaneVR.Framework.Components;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRBullet : MonoBehaviour
|
||||
{
|
||||
public float Speed;
|
||||
public float Gravity;
|
||||
public float TimeToLive;
|
||||
public float Elapsed;
|
||||
public LayerMask LayerMask;
|
||||
|
||||
public bool Hit;
|
||||
|
||||
public HVRGunBase Gun { get; set; }
|
||||
|
||||
//public UnityEvent
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Elapsed = 0f;
|
||||
Hit = false;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
//d = vt;
|
||||
|
||||
Elapsed += Time.deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: babd6ea8b8aeb3d4aa046f31d4b6cce8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRBulletEmitter : HVRGunEmitterBase
|
||||
{
|
||||
public override void Emit()
|
||||
{
|
||||
var clone = Instantiate(Prefab);
|
||||
var rb = clone.GetRigidbody();
|
||||
if (!rb)
|
||||
return;
|
||||
Launch(rb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2ba0ca1bfc7cc54891c0fd0342b7489
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,467 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRCockingHandle : HVRGunPart
|
||||
{
|
||||
|
||||
[Header("Settings")]
|
||||
|
||||
[Tooltip("Forward speed of the slide when released")]
|
||||
public float ForwardSpeed = 10f;
|
||||
|
||||
[Tooltip("Faux difficulty for pulling back the handle")]
|
||||
public float Difficulty = .05f;
|
||||
|
||||
[Tooltip("If the handle was popped open due to out of ammo, it will release immediately upon being grabbed")]
|
||||
public bool ImmediateReleaseWhenOpen = true;
|
||||
|
||||
[Tooltip("If true, locks back even if the handle isn't reciprocating")]
|
||||
public bool LockBackOverride;
|
||||
|
||||
public HVRCockingHandleType Type;
|
||||
|
||||
[Header("Lock Options")]
|
||||
public bool LocksForward;
|
||||
|
||||
public bool TriggerUnlocks;
|
||||
public float TriggerThreshold = .7f;
|
||||
|
||||
[Tooltip("Hand must move this fast to unlock the handle")]
|
||||
public float AccelerationThreshold = 2f;
|
||||
|
||||
[Header("Components")]
|
||||
|
||||
public HVRGrabbable Grabbable;
|
||||
|
||||
[Tooltip("Bolt that moves with the charging handle, pump")]
|
||||
public HVRGunBolt Bolt;
|
||||
|
||||
|
||||
[Header("Editor Positions")]
|
||||
|
||||
[Tooltip("Position to reach to eject the chambered round")]
|
||||
public Vector3 EjectPosition;
|
||||
|
||||
[Tooltip("Position to reach that will chamber a round.")]
|
||||
public Vector3 ChamberRoundPosition;
|
||||
|
||||
public List<HVRGunPart> AnimatedParts = new List<HVRGunPart>();
|
||||
|
||||
[Header("Slide Events")]
|
||||
public UnityEvent Released = new UnityEvent();
|
||||
public UnityEvent EjectReached = new UnityEvent();
|
||||
public UnityEvent ChamberRound = new UnityEvent();
|
||||
|
||||
|
||||
private Transform _grabbedPositionTracker;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The offset of the cocking handle when it's grabbed
|
||||
/// </summary>
|
||||
protected float GrabOffset { get; set; }
|
||||
|
||||
public bool EmptyOpen { get; protected set; }
|
||||
|
||||
public Vector3 ForwardPositionWorld => transform.parent.TransformPoint(ForwardPosition);
|
||||
public Vector3 MaxPositionWorld => transform.parent.TransformPoint(BackwardPosition);
|
||||
|
||||
public Vector3 BackDirectionWorld => (MaxPositionWorld - ForwardPositionWorld).normalized;
|
||||
|
||||
private float _chamberedRequiredDistance;
|
||||
private bool _chamberDistanceReached;
|
||||
|
||||
private float _maximumDistance;
|
||||
|
||||
private float _ejectDistance;
|
||||
private bool _ejectDistanceReached;
|
||||
|
||||
private float _lockDistance;
|
||||
private bool _lockDistanceReached;
|
||||
|
||||
private Vector3 _previousHandPosition;
|
||||
private Vector3 _previousVelocity;
|
||||
private Vector3 _handAcceleration;
|
||||
|
||||
private bool _locked = true;
|
||||
|
||||
private Coroutine _forwardRoutine;
|
||||
|
||||
public virtual bool LocksBack
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Type == HVRCockingHandleType.Reciprocating)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return LockBackOverride;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (!Grabbable)
|
||||
{
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
}
|
||||
|
||||
if (Grabbable)
|
||||
{
|
||||
Grabbable.HandGrabbed.AddListener(OnGrabbed);
|
||||
Grabbable.HandReleased.AddListener(OnReleased);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"{name} is missing it's grabbable component.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
var go = new GameObject("GrabTracker");
|
||||
go.transform.parent = transform.parent;
|
||||
_grabbedPositionTracker = go.transform;
|
||||
|
||||
_chamberedRequiredDistance = Vector3.Distance(ChamberRoundPosition, ForwardPosition);
|
||||
_maximumDistance = Vector3.Distance(BackwardPosition, ForwardPosition);
|
||||
_ejectDistance = Vector3.Distance(EjectPosition, ForwardPosition);
|
||||
_lockDistance = _maximumDistance * .05f;
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
Grabbable.CanBeGrabbed = true;
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
Grabbable.CanBeGrabbed = false;
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (Grabbable.HandGrabbers.Count > 0)
|
||||
{
|
||||
UpdateHandTracking();
|
||||
|
||||
if (_locked)
|
||||
{
|
||||
if (CheckUnlock())
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if (_locked && LocksForward)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pullDirection = (Grabbable.HandGrabbers[0].TrackedController.position - _grabbedPositionTracker.position);
|
||||
var backDirection = (MaxPositionWorld - ForwardPositionWorld).normalized * 10;
|
||||
var amount = Vector3.Dot(pullDirection, backDirection) * Difficulty;
|
||||
|
||||
if (amount + GrabOffset > 0)
|
||||
{
|
||||
UpdatePosition(amount);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.localPosition = ForwardPosition;
|
||||
}
|
||||
|
||||
var distance = Vector3.Distance(transform.position, ForwardPositionWorld);
|
||||
|
||||
CheckEject(distance);
|
||||
CheckChamberDistance(distance);
|
||||
ClampPullBack(distance, BackDirectionWorld);
|
||||
MoveBolt();
|
||||
AnimateParts();
|
||||
CheckLock(distance);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckLock(float distance)
|
||||
{
|
||||
if (!LocksForward)
|
||||
return;
|
||||
|
||||
if (distance > _lockDistance && !_lockDistanceReached)
|
||||
{
|
||||
_lockDistanceReached = true;
|
||||
}
|
||||
else if (distance < _lockDistance && _lockDistanceReached)
|
||||
{
|
||||
Close();
|
||||
_lockDistanceReached = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePosition(float amount)
|
||||
{
|
||||
transform.position = ForwardPositionWorld + BackDirectionWorld * (amount + GrabOffset);
|
||||
}
|
||||
|
||||
|
||||
public void Lock()
|
||||
{
|
||||
_locked = true;
|
||||
//Debug.Log($"lock");
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
_locked = false;
|
||||
//Debug.Log($"unlock");
|
||||
}
|
||||
|
||||
protected virtual bool CheckUnlock()
|
||||
{
|
||||
if (!LocksForward)
|
||||
return true;
|
||||
|
||||
if (TriggerUnlocks)
|
||||
{
|
||||
if (Grabbable.HandGrabbers.Count > 0)
|
||||
{
|
||||
if (Grabbable.HandGrabbers[0].Controller.Trigger > TriggerThreshold)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_handAcceleration.magnitude > AccelerationThreshold)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void CheckEject(float distance)
|
||||
{
|
||||
if (distance > _ejectDistance && !_ejectDistanceReached)
|
||||
{
|
||||
EjectReached.Invoke();
|
||||
_ejectDistanceReached = true;
|
||||
}
|
||||
else if (distance < _ejectDistance && _ejectDistanceReached)
|
||||
{
|
||||
_ejectDistanceReached = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckChamberDistance(float distance)
|
||||
{
|
||||
if (distance > _chamberedRequiredDistance)
|
||||
{
|
||||
if (!_chamberDistanceReached)
|
||||
{
|
||||
_chamberDistanceReached = true;
|
||||
}
|
||||
}
|
||||
else if (distance < _chamberedRequiredDistance && _chamberDistanceReached)
|
||||
{
|
||||
_chamberDistanceReached = false;
|
||||
ChamberRound.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ClampPullBack(float distance, Vector3 backDirection)
|
||||
{
|
||||
if (distance > _maximumDistance)
|
||||
{
|
||||
transform.localPosition = BackwardPosition;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateHandTracking()
|
||||
{
|
||||
if (!Grabbable.IsBeingHeld)
|
||||
return;
|
||||
|
||||
if (Grabbable.PrimaryGrabber.IsHandGrabber)
|
||||
{
|
||||
var hand = Grabbable.HandGrabbers[0];
|
||||
var velocity = hand.TrackedController.position - _previousHandPosition;
|
||||
_handAcceleration = (velocity - _previousVelocity) / Time.deltaTime;
|
||||
_previousVelocity = velocity;
|
||||
_previousHandPosition = hand.TrackedController.position;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void MoveBolt()
|
||||
{
|
||||
if (Bolt)
|
||||
{
|
||||
if (_ejectDistance == 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var percent = Vector3.Distance(transform.localPosition, ForwardPosition) / _maximumDistance;
|
||||
|
||||
if (percent > .90)
|
||||
{
|
||||
Bolt.IsPushedBack = false;
|
||||
}
|
||||
|
||||
if (Bolt.IsPushedBack && percent < .90)
|
||||
return;
|
||||
Bolt.Move(percent);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void AnimateParts()
|
||||
{
|
||||
var percent = Vector3.Distance(transform.localPosition, ForwardPosition) / _maximumDistance;
|
||||
|
||||
foreach (var part in AnimatedParts)
|
||||
{
|
||||
part.Animate(percent, CycleDirection.Backward);
|
||||
}
|
||||
}
|
||||
|
||||
public void Move(float percent)
|
||||
{
|
||||
transform.localPosition = Vector3.Lerp(ForwardPosition, BackwardPosition, percent);
|
||||
}
|
||||
|
||||
protected virtual void OnGrabbed(HVRHandGrabber grabber, HVRGrabbable slide)
|
||||
{
|
||||
GrabOffset = 0f;
|
||||
|
||||
if (ImmediateReleaseWhenOpen && EmptyOpen && LocksBack)
|
||||
{
|
||||
if (Bolt)
|
||||
{
|
||||
Bolt.IsPushedBack = false;
|
||||
}
|
||||
Grabbable.ForceRelease();
|
||||
}
|
||||
|
||||
_previousHandPosition = grabber.TrackedController.position;
|
||||
_previousVelocity = Vector3.zero;
|
||||
if (Type == HVRCockingHandleType.Pump)
|
||||
{
|
||||
_grabbedPositionTracker.position = grabber.GrabPoint.position;
|
||||
}
|
||||
else
|
||||
{
|
||||
_grabbedPositionTracker.localPosition = transform.parent.InverseTransformPoint(_previousHandPosition);
|
||||
GrabOffset = Vector3.Distance(ForwardPositionWorld, transform.position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected virtual void OnReleased(HVRHandGrabber grabber, HVRGrabbable slide)
|
||||
{
|
||||
EmptyOpen = false;
|
||||
if (Type != HVRCockingHandleType.Pump)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (_forwardRoutine != null)
|
||||
return;
|
||||
StartCoroutine(ForwardRoutine());
|
||||
}
|
||||
|
||||
protected virtual IEnumerator ForwardRoutine()
|
||||
{
|
||||
Grabbable.CanBeGrabbed = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
var distance = Vector3.Distance(transform.localPosition, ForwardPosition);
|
||||
var travel = ForwardSpeed * Time.deltaTime;
|
||||
|
||||
if (distance < travel)
|
||||
{
|
||||
transform.localPosition = ForwardPosition;
|
||||
MoveBolt();
|
||||
AnimateParts();
|
||||
break;
|
||||
}
|
||||
|
||||
transform.localPosition = Vector3.MoveTowards(transform.localPosition, ForwardPosition, travel);
|
||||
AnimateParts();
|
||||
MoveBolt();
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
_forwardRoutine = null;
|
||||
Grabbable.CanBeGrabbed = true;
|
||||
|
||||
if (_chamberDistanceReached)
|
||||
{
|
||||
ChamberRound.Invoke();
|
||||
}
|
||||
|
||||
Released.Invoke();
|
||||
_chamberDistanceReached = false;
|
||||
_ejectDistanceReached = false;
|
||||
EmptyOpen = false;
|
||||
|
||||
if (LocksForward)
|
||||
{
|
||||
Lock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void PushBack()
|
||||
{
|
||||
if (LocksBack)
|
||||
{
|
||||
transform.localPosition = EjectPosition;
|
||||
EmptyOpen = true;
|
||||
_chamberDistanceReached = true;
|
||||
if (Bolt)
|
||||
{
|
||||
Bolt.Move(1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Animate(float percent, CycleDirection direction)
|
||||
{
|
||||
if (Type == HVRCockingHandleType.Reciprocating)
|
||||
{
|
||||
Move(percent);
|
||||
}
|
||||
}
|
||||
|
||||
//public void OnDrawGizmosSelected()
|
||||
//{
|
||||
// Gizmos.color = Color.green;
|
||||
// Gizmos.DrawCube(ForwardPositionWorld, new Vector3(.025f, .025f, .025f));
|
||||
// Gizmos.color = Color.red;
|
||||
// Gizmos.DrawCube(MaxPositionWorld, new Vector3(.025f, .025f, .025f));
|
||||
// Gizmos.color = Color.yellow;
|
||||
// Gizmos.DrawCube(transform.parent.TransformPoint(EjectPosition), new Vector3(.025f, .025f, .025f));
|
||||
// Gizmos.color = Color.cyan;
|
||||
// Gizmos.DrawCube(transform.parent.TransformPoint(ChamberRoundPosition), new Vector3(.025f, .025f, .025f));
|
||||
//}
|
||||
}
|
||||
|
||||
public enum HVRCockingHandleType
|
||||
{
|
||||
Reciprocating, NonReciprocating, Pump
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5b6a3a6b34cc6743b0fff4f3ee25c54
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Collections;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
|
||||
public class HVRGrabMagazine : HVRHandGrabEvent
|
||||
{
|
||||
public float GrabDelay = .05f;
|
||||
public HVRSocket MagSocket;
|
||||
|
||||
protected WaitForSeconds Timeout;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
Timeout = new WaitForSeconds(GrabDelay);
|
||||
}
|
||||
|
||||
protected override bool CheckEnableGrab()
|
||||
{
|
||||
return MagSocket && MagSocket.IsGrabbing;
|
||||
}
|
||||
|
||||
protected override void OnHandGrabbed(HVRHandGrabber hand, HVRGrabbable arg1)
|
||||
{
|
||||
base.OnHandGrabbed(hand, arg1);
|
||||
if (MagSocket && MagSocket.GrabbedTarget)
|
||||
{
|
||||
var ammo = MagSocket.GrabbedTarget;
|
||||
MagSocket.ForceRelease();
|
||||
StartCoroutine(GrabRoutine(ammo, hand));
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerator GrabRoutine(HVRGrabbable ammo, HVRHandGrabber hand)
|
||||
{
|
||||
//yield return Timeout;
|
||||
yield return new WaitForSeconds(GrabDelay);
|
||||
if (ammo && !ammo.IsBeingHeld && !hand.GrabbedTarget)
|
||||
{
|
||||
hand.TryGrab(ammo, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ead9473e10324d4684477e2ecd88999
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1165
Assets/HurricaneVR/Framework/Scripts/Weapons/Guns/HVRGunBase.cs
Normal file
1165
Assets/HurricaneVR/Framework/Scripts/Weapons/Guns/HVRGunBase.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1dddf24d500dae7489529737f2333e93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRGunBolt : HVRGunPart
|
||||
{
|
||||
public bool IsPushedBack { get; set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
public void Move(float percent)
|
||||
{
|
||||
if (float.IsNaN(percent))
|
||||
return;
|
||||
transform.localPosition = Vector3.Lerp(ForwardPosition, BackwardPosition, percent);
|
||||
}
|
||||
|
||||
public virtual void PushBack()
|
||||
{
|
||||
transform.localPosition = BackwardPosition;
|
||||
IsPushedBack = true;
|
||||
}
|
||||
public override void Animate(float percent, CycleDirection direction)
|
||||
{
|
||||
Move(percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da604da12e078d7458bac76897f36d1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public abstract class HVRGunEmitterBase : MonoBehaviour
|
||||
{
|
||||
public float LaunchRadius = .05f;
|
||||
|
||||
public float MinVelocity = 4f;
|
||||
public float MaxVelocity = 6f;
|
||||
|
||||
public Vector3 MinAngularVelocity = new Vector3(0f, 8f, 0f);
|
||||
public Vector3 MaxAngularVelocity = new Vector3(0f, 10f, 0f);
|
||||
|
||||
public HVRGunBase Gun;
|
||||
|
||||
public GameObject Prefab;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Emit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Launch(Rigidbody rb)
|
||||
{
|
||||
if (!rb)
|
||||
return;
|
||||
rb.velocity = Vector3.zero;
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
rb.transform.position = transform.position;
|
||||
rb.transform.rotation = transform.rotation;
|
||||
|
||||
|
||||
var xy = Random.insideUnitCircle * LaunchRadius;
|
||||
var launchDirection = transform.right + new Vector3(0f, xy.x, xy.y);
|
||||
|
||||
rb.velocity = launchDirection * Random.Range(MinVelocity, MaxVelocity);
|
||||
rb.AddRelativeTorque(
|
||||
Random.Range(MinAngularVelocity.x, MaxAngularVelocity.x),
|
||||
Random.Range(MinAngularVelocity.y, MaxAngularVelocity.y),
|
||||
Random.Range(MinAngularVelocity.z, MaxAngularVelocity.z),
|
||||
ForceMode.VelocityChange
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0c4c4c9f5c075a4ba3413652b9cd352
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
[CreateAssetMenu(menuName = "HurricaneVR/GunHaptics", fileName = "GunHaptics")]
|
||||
public class HVRGunHaptics : ScriptableObject
|
||||
{
|
||||
public void Reset()
|
||||
{
|
||||
Fire = new HapticData(.20f, .70f, 150f);
|
||||
DryFire = new HapticData(.04f, .5f, 50f);
|
||||
TriggerSqueezed = new HapticData(.1f, .01f, 60f);
|
||||
TriggeredReleased = new HapticData(.025f, .2f, 45f);
|
||||
|
||||
CockingHandleEject = new HapticData(.05f, 200f, .22f);
|
||||
CockingHandleChamberedRound = new HapticData(.05f, 200f, .22f);
|
||||
CockingHandleReleased = new HapticData(.05f, 200f, .22f);
|
||||
AmmoSocketed = new HapticData(.05f, 200f, .22f);
|
||||
AmmoSocketReleased = new HapticData(.05f, 200f, .22f);
|
||||
}
|
||||
|
||||
public HapticData DryFire;
|
||||
public HapticData Fire;
|
||||
public HapticData TriggeredReleased;
|
||||
public HapticData TriggerSqueezed;
|
||||
|
||||
public HapticData CockingHandleEject;
|
||||
public HapticData CockingHandleChamberedRound;
|
||||
public HapticData CockingHandleReleased;
|
||||
|
||||
public HapticData AmmoSocketed;
|
||||
public HapticData AmmoSocketReleased;
|
||||
|
||||
public float TriggerSqueezeStop = .7f;
|
||||
public float TriggerSqueezeStart = .1f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 226cce0b7ab93444c9da83b531f6aa9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRGunPart : MonoBehaviour
|
||||
{
|
||||
[Header("Gun Part Positions (Base Class)")]
|
||||
public Vector3 ForwardPosition;
|
||||
public Vector3 BackwardPosition;
|
||||
|
||||
public virtual void Animate(float percent, CycleDirection direction)
|
||||
{
|
||||
if (float.IsNaN(percent))
|
||||
return;
|
||||
transform.localPosition = Vector3.Lerp(ForwardPosition, BackwardPosition, percent);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CycleDirection
|
||||
{
|
||||
Backward,
|
||||
Forward
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed770b5ca1394bd46a54e22aedf55187
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.Collections;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRMagazineSocket : HVRSocket
|
||||
{
|
||||
[Header("Magazine Socket Fields")]
|
||||
public bool Animate = true;
|
||||
public float AnimationTime = .2f;
|
||||
public float MagazineTravel = .1f;
|
||||
public bool AnimateEject;
|
||||
public float EjectTime = .2f;
|
||||
|
||||
public Transform MagazineAxis;
|
||||
|
||||
protected Vector3 MagazineDirection => MagazineAxis ? MagazineAxis.forward : -transform.up;
|
||||
|
||||
protected override void OnGrabbableParented(HVRGrabbable grabbable)
|
||||
{
|
||||
if (Animate)
|
||||
{
|
||||
StartCoroutine(LoadAnimationRoutine(grabbable));
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnGrabbableParented(grabbable);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IEnumerator LoadAnimationRoutine(HVRGrabbable grabbable)
|
||||
{
|
||||
CanRemoveGrabbable = false;
|
||||
|
||||
var elapsed = 0f;
|
||||
var targetPosition = GetTargetPosition(grabbable);
|
||||
var targetRotation = GetTargetRotation(grabbable);
|
||||
var direction = targetPosition - grabbable.transform.localPosition;
|
||||
var speed = direction.magnitude / AnimationTime;
|
||||
|
||||
grabbable.transform.position = transform.position + MagazineDirection * MagazineTravel;
|
||||
grabbable.transform.localRotation = targetRotation;
|
||||
|
||||
while (elapsed < AnimationTime)
|
||||
{
|
||||
grabbable.transform.localPosition = Vector3.MoveTowards(grabbable.transform.localPosition, targetPosition, speed * Time.deltaTime);
|
||||
|
||||
elapsed += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
grabbable.transform.localPosition = targetPosition;
|
||||
|
||||
CanRemoveGrabbable = true;
|
||||
}
|
||||
|
||||
protected virtual IEnumerator EjectAnimationRoutine(HVRGrabbable grabbable)
|
||||
{
|
||||
grabbable.CanBeGrabbed = false;
|
||||
grabbable.Rigidbody.useGravity = false;
|
||||
var elapsed = 0f;
|
||||
var direction = MagazineDirection;
|
||||
var speed = MagazineTravel / EjectTime;
|
||||
var target = grabbable.transform.position + direction.normalized * MagazineTravel;
|
||||
|
||||
while (elapsed < EjectTime && grabbable)
|
||||
{
|
||||
grabbable.transform.position = Vector3.MoveTowards(grabbable.transform.position, target, speed * Time.deltaTime);
|
||||
grabbable.Rigidbody.velocity = Vector3.zero;
|
||||
grabbable.Rigidbody.angularVelocity = Vector3.zero;
|
||||
elapsed += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
//magazine might be destroyed if it's empty
|
||||
if (grabbable)
|
||||
{
|
||||
grabbable.Rigidbody.useGravity = true;
|
||||
grabbable.CanBeGrabbed = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnReleased(HVRGrabbable grabbable)
|
||||
{
|
||||
base.OnReleased(grabbable);
|
||||
if (AnimateEject && gameObject.activeInHierarchy)
|
||||
{
|
||||
StartCoroutine(EjectAnimationRoutine(grabbable));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a13d52c8343fece4a9e5696716c06f69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRPistol : HVRGunBase
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbd328f6ceb25be44b7a7b2cdd971854
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared.Utilities;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRPooledEmitter : HVRGunEmitterBase
|
||||
{
|
||||
public int MinLife = 5;
|
||||
public int MaxLife = 10;
|
||||
public int MaxObjects = 30;
|
||||
|
||||
public HideFlags HideFlags = HideFlags.HideInHierarchy;
|
||||
|
||||
private readonly List<HVRPooledObjectTracker> _objects = new List<HVRPooledObjectTracker>();
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
for (int i = 0; i < MaxObjects; i++)
|
||||
{
|
||||
if (Prefab)
|
||||
{
|
||||
_objects.Add(new HVRPooledObjectTracker());
|
||||
_objects[i].Object = Instantiate(Prefab);
|
||||
_objects[i].Object.SetActive(false);
|
||||
_objects[i].Rigidbody = _objects[i].Object.GetRigidbody();
|
||||
_objects[i].Object.hideFlags = HideFlags;
|
||||
_objects[i].Colliders = _objects[i].Object.GetComponentsInChildren<Collider>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
for (int i = 0; i < _objects.Count; i++)
|
||||
{
|
||||
if (_objects[i].Object.activeSelf)
|
||||
{
|
||||
_objects[i].Elapsed += Time.deltaTime;
|
||||
if (_objects[i].Elapsed > _objects[i].TimeToLive)
|
||||
{
|
||||
_objects[i].Object.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Emit()
|
||||
{
|
||||
HVRPooledObjectTracker tracker = null;
|
||||
|
||||
var time = -1f;
|
||||
|
||||
for (int i = 0; i < _objects.Count; i++)
|
||||
{
|
||||
if (!_objects[i].Object.activeSelf)
|
||||
{
|
||||
tracker = _objects[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (_objects[i].Elapsed > time)
|
||||
{
|
||||
tracker = _objects[i];
|
||||
time = _objects[i].Elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
if (tracker != null)
|
||||
{
|
||||
tracker.Elapsed = 0f;
|
||||
tracker.TimeToLive = Random.Range(MinLife, MaxLife);
|
||||
tracker.Object.SetActive(true);
|
||||
var rb = tracker.Rigidbody;
|
||||
if (rb)
|
||||
{
|
||||
Launch(rb);
|
||||
if (Gun)
|
||||
{
|
||||
Gun.IgnoreCollision(tracker.Colliders, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class HVRPooledObjectTracker
|
||||
{
|
||||
public GameObject Object;
|
||||
public Rigidbody Rigidbody;
|
||||
public float Elapsed;
|
||||
public float TimeToLive;
|
||||
public Collider[] Colliders;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 615314fd4a55b7e42af9ee3b76badb4f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRShotgun : HVRGunBase
|
||||
{
|
||||
[Header("Shotgun Settings")]
|
||||
public int NumberOfPellets = 5;
|
||||
public float ShotRadius = 0.05f;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
Ammo = GetComponent<HVRShotgunMagazine>();
|
||||
}
|
||||
|
||||
protected override void OnFire(Vector3 direction)
|
||||
{
|
||||
for (int i = 0; i < NumberOfPellets; i++)
|
||||
{
|
||||
var xy = Random.insideUnitCircle * ShotRadius;
|
||||
var newDirection = direction + transform.TransformDirection(xy);
|
||||
FireBullet(newDirection);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnCockingHandleEjected()
|
||||
{
|
||||
base.OnCockingHandleEjected();
|
||||
if (ChamberedCasing && ChamberedCasing.activeSelf)
|
||||
{
|
||||
EjectCasing();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAmmoSocketed(HVRGrabberBase grabber, HVRGrabbable grabbable)
|
||||
{
|
||||
AmmoSocketedHaptics();
|
||||
}
|
||||
|
||||
protected override void OnAmmoSocketReleased(HVRGrabberBase arg0, HVRGrabbable arg1)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d4f312e756ab8b44bed084477f9ba1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns
|
||||
{
|
||||
public class HVRTriggerAnimator : MonoBehaviour
|
||||
{
|
||||
public bool Rotate = true;
|
||||
public Quaternion StartRotation;
|
||||
public Quaternion EndRotation;
|
||||
|
||||
public bool Move = false;
|
||||
public Vector3 ForwardPosition;
|
||||
public Vector3 BackwardPosition;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (StartRotation.w == 0f)
|
||||
{
|
||||
StartRotation = transform.localRotation;
|
||||
}
|
||||
|
||||
if (EndRotation.w == 0f)
|
||||
{
|
||||
EndRotation = transform.localRotation;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Animate(float trigger)
|
||||
{
|
||||
if (Rotate)
|
||||
{
|
||||
transform.localRotation = Quaternion.Lerp(StartRotation, EndRotation, trigger);
|
||||
}
|
||||
|
||||
if (Move)
|
||||
{
|
||||
transform.localPosition = Vector3.Lerp(ForwardPosition, BackwardPosition, trigger);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb7bbd5fbb64d0646a11fe1ab1882b15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c2df5b3fe73cc54791749a805e37687
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns.PartFinders
|
||||
{
|
||||
public class HVRChamberedCasingFinder : MonoBehaviour
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ada3d5a28435ca42ab5cbc53dc7c2a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns.PartFinders
|
||||
{
|
||||
public class HVRChamberedRoundFinder : MonoBehaviour
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b67ef4552bd2b1f49894e6ff773d67da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons.Guns.PartFinders
|
||||
{
|
||||
public class HVRMagazineFinder : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ac97456e56d5c543861420a61ed719b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
66
Assets/HurricaneVR/Framework/Scripts/Weapons/HVRAmmo.cs
Normal file
66
Assets/HurricaneVR/Framework/Scripts/Weapons/HVRAmmo.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Components;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons
|
||||
{
|
||||
public class HVRAmmo : HVRDamageProvider
|
||||
{
|
||||
[Tooltip("Magazine Starting Count")]
|
||||
public int StartingCount = 15;
|
||||
[Tooltip("Max bullets allowed in the magazine")]
|
||||
public int MaxCount;
|
||||
|
||||
[Tooltip("Bullet Range")]
|
||||
public float MaxRange = 40f;
|
||||
|
||||
[Header("Magazine Cleanup")]
|
||||
[Tooltip("Should the empty magazine be destroyed")]
|
||||
public bool DestroyIfEmpty = true;
|
||||
[Tooltip("How long to wait after ejecting the magazine to destroy it")]
|
||||
public float EmptyDestroyTimer = 3f;
|
||||
|
||||
[Header("Debug")]
|
||||
public int CurrentCount;
|
||||
|
||||
public bool HasAmmo => CurrentCount > 0;
|
||||
public bool IsEmpty => CurrentCount <= 0;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
CurrentCount = StartingCount;
|
||||
}
|
||||
|
||||
public virtual void AddBullet()
|
||||
{
|
||||
CurrentCount++;
|
||||
}
|
||||
|
||||
public virtual bool CanAddBullet()
|
||||
{
|
||||
return CurrentCount < MaxCount;
|
||||
}
|
||||
|
||||
public virtual bool TryAddBullet()
|
||||
{
|
||||
if (CanAddBullet())
|
||||
{
|
||||
AddBullet();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void RemoveBullet()
|
||||
{
|
||||
CurrentCount--;
|
||||
if (CurrentCount < 0)
|
||||
CurrentCount = 0;
|
||||
}
|
||||
|
||||
public virtual void StartDestroy()
|
||||
{
|
||||
Destroy(gameObject, EmptyDestroyTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1366c90de78d471fb0da0dd5a440fe4b
|
||||
timeCreated: 1604445095
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.ControllerInput;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using HurricaneVR.Framework.Weapons.Guns;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons
|
||||
{
|
||||
|
||||
public class HVRAmmoReleaseAction : HVRInputAction
|
||||
{
|
||||
public HVRGunBase Gun { get; private set; }
|
||||
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
Gun = GetComponent<HVRGunBase>();
|
||||
}
|
||||
|
||||
|
||||
protected override void CheckInput(HVRController controller)
|
||||
{
|
||||
var release = false;
|
||||
|
||||
|
||||
if (controller.ControllerType == HVRControllerType.WMR)
|
||||
{
|
||||
release = controller.Side == HVRHandSide.Right ? controller.TrackPadLeft.JustActivated : controller.TrackPadRight.JustActivated;
|
||||
}
|
||||
else if (controller.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
release = HVRInputManager.Instance.RightController.TrackPadDown.JustActivated;
|
||||
}
|
||||
else
|
||||
{
|
||||
release = controller.PrimaryButtonState.JustActivated;
|
||||
}
|
||||
|
||||
if (release && Gun)
|
||||
{
|
||||
Gun.ReleaseAmmo();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb5167cc14034676a2d0d91513d89cf3
|
||||
timeCreated: 1604445111
|
||||
92
Assets/HurricaneVR/Framework/Scripts/Weapons/HVRGunSounds.cs
Normal file
92
Assets/HurricaneVR/Framework/Scripts/Weapons/HVRGunSounds.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons
|
||||
{
|
||||
public class HVRGunSounds : MonoBehaviour
|
||||
{
|
||||
public AudioClip Fired;
|
||||
public AudioClip OutOfAmmo;
|
||||
|
||||
//public AudioClip AmmoInserted;
|
||||
//public AudioClip AmmoReleased;
|
||||
|
||||
public AudioClip SlideBack;
|
||||
public AudioClip SlideForward;
|
||||
|
||||
public List<AudioClip> FiredVariations = new List<AudioClip>();
|
||||
//public List<AudioClip> AmmoInsertedVariations = new List<AudioClip>();
|
||||
//public List<AudioClip> AmmoReleasedVariations = new List<AudioClip>();
|
||||
|
||||
public List<AudioClip> SlideBackVariations = new List<AudioClip>();
|
||||
public List<AudioClip> SlideForwardVariations = new List<AudioClip>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
AddVariation(Fired, FiredVariations);
|
||||
//AddVariation(AmmoInserted, AmmoInsertedVariations);
|
||||
//AddVariation(AmmoReleased, AmmoReleasedVariations);
|
||||
AddVariation(SlideBack, SlideBackVariations);
|
||||
AddVariation(SlideForward, SlideForwardVariations);
|
||||
}
|
||||
|
||||
public virtual void PlayGunFire()
|
||||
{
|
||||
PlayVariation(FiredVariations);
|
||||
}
|
||||
|
||||
//public virtual void PlayAmmoInserted()
|
||||
//{
|
||||
// PlayVariation(AmmoInsertedVariations);
|
||||
//}
|
||||
|
||||
//public virtual void PlayAmmoReleased()
|
||||
//{
|
||||
// PlayVariation(AmmoReleasedVariations);
|
||||
//}
|
||||
|
||||
public virtual void PlayOutOfAmmo()
|
||||
{
|
||||
PlayClip(OutOfAmmo);
|
||||
}
|
||||
|
||||
public virtual void PlaySlideForward()
|
||||
{
|
||||
PlayVariation(SlideForwardVariations);
|
||||
}
|
||||
|
||||
public virtual void PlaySlideBack()
|
||||
{
|
||||
PlayVariation(SlideBackVariations);
|
||||
}
|
||||
|
||||
protected virtual void PlayVariation(List<AudioClip> variations)
|
||||
{
|
||||
if (variations.Count == 0)
|
||||
return;
|
||||
|
||||
var index = Random.Range(0, variations.Count);
|
||||
var sfx = variations[index];
|
||||
|
||||
PlayClip(sfx);
|
||||
}
|
||||
|
||||
protected virtual void PlayClip(AudioClip clip)
|
||||
{
|
||||
if (!clip)
|
||||
return;
|
||||
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(clip, transform.position);
|
||||
}
|
||||
|
||||
private void AddVariation(AudioClip clip, List<AudioClip> variations)
|
||||
{
|
||||
if (clip && !variations.Contains(clip))
|
||||
{
|
||||
variations.Add(clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85b4ee1a35cc4bb19411742b63218921
|
||||
timeCreated: 1605976440
|
||||
199
Assets/HurricaneVR/Framework/Scripts/Weapons/HVRRecoil.cs
Normal file
199
Assets/HurricaneVR/Framework/Scripts/Weapons/HVRRecoil.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core.ScriptableObjects;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons
|
||||
{
|
||||
public class HVRRecoil : MonoBehaviour
|
||||
{
|
||||
public HVRRecoilSettings Settings;
|
||||
|
||||
public UpRecoilType UpRecoilType;
|
||||
|
||||
public Transform UpRecoil;
|
||||
public Transform BackRecoil;
|
||||
|
||||
public Vector3 CurrentForce;
|
||||
|
||||
[Tooltip("If the gun is rotated set to true to reverse the x torque direction")]
|
||||
public bool TorqueAxisReversed;
|
||||
|
||||
private float _timeSinceLastRecoil;
|
||||
private float _recoveryTimer;
|
||||
private bool _recoil;
|
||||
|
||||
|
||||
public Rigidbody Rigidbody => UpRecoilType == Weapons.UpRecoilType.TorqueHand ? HandRigidBody : GunRigidBody;
|
||||
|
||||
public Rigidbody HandRigidBody { get; set; }
|
||||
|
||||
public Rigidbody GunRigidBody { get; set; }
|
||||
|
||||
public bool TwoHanded { get; set; }
|
||||
|
||||
public float SideToSide
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Settings || !Settings.RandomSideToSideRecoil)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
if (TwoHanded)
|
||||
return Random.Range(Settings.TwoHandSideToSideMin, Settings.TwoHandSideToSideMax);
|
||||
|
||||
return Random.Range(Settings.SideToSideMin, Settings.SideToSideMax);
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
GunRigidBody = gameObject.GetRigidbody();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
_timeSinceLastRecoil += Time.fixedDeltaTime;
|
||||
|
||||
if (!Rigidbody || !Settings)
|
||||
return;
|
||||
|
||||
ApplyRecoil();
|
||||
CheckRecovery();
|
||||
ApplyConstantForce();
|
||||
|
||||
|
||||
_recoil = false;
|
||||
}
|
||||
|
||||
private void ApplyRecoil()
|
||||
{
|
||||
if (_recoil)
|
||||
{
|
||||
var upForce = Settings.UpForce;
|
||||
var backForce = Settings.BackwardsForce;
|
||||
|
||||
if (TwoHanded && Settings.UseTwoHandRecoilForce)
|
||||
{
|
||||
upForce = Settings.TwoHandUpForce;
|
||||
backForce = Settings.TwoHandBackwardsForce;
|
||||
}
|
||||
|
||||
if (Settings.ImpulseForce)
|
||||
{
|
||||
ApplyImpulseRecoil(upForce, backForce);
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentForce.y += upForce;
|
||||
CurrentForce.z += backForce;
|
||||
}
|
||||
|
||||
if (Settings.RandomSideToSideRecoil)
|
||||
{
|
||||
//Rigidbody.AddForceAtPosition(UpRecoil.right * SideToSide, UpRecoil.position, ForceMode.Impulse);
|
||||
Rigidbody.AddTorque(transform.up * SideToSide, ForceMode.Impulse);
|
||||
CurrentForce.x += SideToSide / Time.fixedDeltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.LimitRecoilForce)
|
||||
{
|
||||
var maxForce = Settings.MaxUpForce;
|
||||
if (Settings.UseTwoHandMaxUpforce && TwoHanded)
|
||||
{
|
||||
maxForce = Settings.TwoHandMaxUpForce;
|
||||
}
|
||||
|
||||
var maxSideForce = Settings.MaxSideForce;
|
||||
if (Settings.UseTwoHandMaxSideForce && TwoHanded)
|
||||
{
|
||||
maxSideForce = Settings.TwoHandMaxSideForce;
|
||||
}
|
||||
|
||||
CurrentForce.x = Mathf.Clamp(CurrentForce.x, -maxSideForce, maxSideForce);
|
||||
CurrentForce.y = Mathf.Clamp(CurrentForce.y, 0, maxForce);
|
||||
CurrentForce.z = Mathf.Clamp(CurrentForce.z, 0, Settings.MaxBackForce);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckRecovery()
|
||||
{
|
||||
var delay = TwoHanded ? Settings.TwoHandedRecoveryDelay : Settings.RecoveryDelay;
|
||||
|
||||
if (_timeSinceLastRecoil > delay)
|
||||
{
|
||||
var recoveryTime = TwoHanded ? Settings.TwoHandedRecoveryTime : Settings.RecoveryTime;
|
||||
_recoveryTimer += Time.fixedDeltaTime;
|
||||
var percentRecovered = Mathf.Clamp(_recoveryTimer / recoveryTime, 0, 1);
|
||||
|
||||
CurrentForce *= 1 - percentRecovered;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyConstantForce()
|
||||
{
|
||||
if (UpRecoilType == UpRecoilType.UpRecoil)
|
||||
{
|
||||
if (UpRecoil)
|
||||
{
|
||||
Rigidbody.AddForceAtPosition(UpRecoil.up * CurrentForce.y, UpRecoil.position, ForceMode.Force);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Rigidbody.AddTorque(transform.right * (CurrentForce.y * (TorqueAxisReversed ? -1 : 1)), ForceMode.Force);
|
||||
}
|
||||
|
||||
Rigidbody.AddTorque(transform.up * CurrentForce.x, ForceMode.Force);
|
||||
|
||||
if (BackRecoil)
|
||||
{
|
||||
Rigidbody.AddForceAtPosition(BackRecoil.forward * CurrentForce.z, BackRecoil.position, ForceMode.Force);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyImpulseRecoil(float upForce, float backForce)
|
||||
{
|
||||
if (UpRecoilType == Weapons.UpRecoilType.UpRecoil)
|
||||
{
|
||||
if (UpRecoil)
|
||||
{
|
||||
Rigidbody.AddForceAtPosition(UpRecoil.up * upForce, UpRecoil.position, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Rigidbody.AddTorque(transform.right * (upForce *( TorqueAxisReversed ? -1 : 1)), ForceMode.Impulse);
|
||||
}
|
||||
|
||||
|
||||
if (BackRecoil)
|
||||
{
|
||||
Rigidbody.AddForceAtPosition(BackRecoil.forward * backForce, BackRecoil.position, ForceMode.Impulse);
|
||||
}
|
||||
|
||||
CurrentForce.y += upForce / Time.fixedDeltaTime;
|
||||
CurrentForce.z += backForce / Time.fixedDeltaTime;
|
||||
}
|
||||
|
||||
public void Recoil()
|
||||
{
|
||||
_recoil = true;
|
||||
_timeSinceLastRecoil = 0f;
|
||||
_recoveryTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public enum UpRecoilType
|
||||
{
|
||||
UpRecoil,
|
||||
TorqueHand,
|
||||
TorqueGun
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83b3fda07db74abe982337dd671606de
|
||||
timeCreated: 1605382407
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Collections;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
|
||||
namespace HurricaneVR.Framework.Weapons
|
||||
{
|
||||
public class HVRShotgunAmmoSocket : HVRSocket
|
||||
{
|
||||
public HVRShotgunMagazine ShotgunMagazine;
|
||||
|
||||
public override bool CanHover(HVRGrabbable grabbable)
|
||||
{
|
||||
if (!ShotgunMagazine.CanAddBullet())
|
||||
return false;
|
||||
|
||||
return base.CanHover(grabbable);
|
||||
}
|
||||
|
||||
public override bool CanGrab(HVRGrabbable grabbable)
|
||||
{
|
||||
if (!ShotgunMagazine.CanAddBullet())
|
||||
return false;
|
||||
|
||||
return base.CanGrab(grabbable);
|
||||
}
|
||||
|
||||
protected override void OnGrabbed(HVRGrabArgs args)
|
||||
{
|
||||
base.OnGrabbed(args);
|
||||
if (ShotgunMagazine.TryAddBullet())
|
||||
{
|
||||
StartCoroutine(DropAndDestroy(args.Grabbable));
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(Drop(args.Grabbable));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator DropAndDestroy(HVRGrabbable grabbable)
|
||||
{
|
||||
yield return null;
|
||||
grabbable.ForceRelease();
|
||||
Destroy(grabbable.gameObject);
|
||||
}
|
||||
|
||||
private IEnumerator Drop(HVRGrabbable grabbable)
|
||||
{
|
||||
yield return null;
|
||||
grabbable.ForceRelease();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af2a65f4bdd647958bec95376f37db27
|
||||
timeCreated: 1606176025
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace HurricaneVR.Framework.Weapons
|
||||
{
|
||||
public class HVRShotgunMagazine : HVRAmmo
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ece64f546b4b471f9761a7aca682299f
|
||||
timeCreated: 1606175343
|
||||
Reference in New Issue
Block a user