Replace UltimateXR with HurricaneVR

This commit is contained in:
2024-08-08 17:01:07 +02:00
parent e8658374d6
commit fb21dbbb73
5932 changed files with 358362 additions and 2174150 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 83c3bfee872eb894785139b7a23da4f5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4961525acc8e94846ab15a6ebeed42a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4daa695d62072d64f89a844cb8274fda
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
});
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c20151e078b7ac4a9673ee89501f652
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95ad415173bd87641b0911ab7c483a6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9e9a76a97fc7a0f4a977816fe4d34add
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2438268ac55dd3544a75a36f11afc5a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85b2b482c7b701c4a91db69ec8b0ac1e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c5fea5ebfaa0a0d448962e145ae9a991
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9329b61191544954aadf4fa05841e222
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
using System.Collections;
using UnityEngine;
namespace HurricaneVR.Framework.Weapons.Guns
{
public class HVRAutomaticGun : HVRGunBase
{
protected override void Awake()
{
base.Awake();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f9db1f9e84328a44ae9e19e161049a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: babd6ea8b8aeb3d4aa046f31d4b6cce8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2ba0ca1bfc7cc54891c0fd0342b7489
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a5b6a3a6b34cc6743b0fff4f3ee25c54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ead9473e10324d4684477e2ecd88999
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1dddf24d500dae7489529737f2333e93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da604da12e078d7458bac76897f36d1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b0c4c4c9f5c075a4ba3413652b9cd352
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 226cce0b7ab93444c9da83b531f6aa9a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed770b5ca1394bd46a54e22aedf55187
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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));
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a13d52c8343fece4a9e5696716c06f69
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
using System.Collections;
using UnityEngine;
namespace HurricaneVR.Framework.Weapons.Guns
{
public class HVRPistol : HVRGunBase
{
protected override void Awake()
{
base.Awake();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbd328f6ceb25be44b7a7b2cdd971854
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 615314fd4a55b7e42af9ee3b76badb4f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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)
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d4f312e756ab8b44bed084477f9ba1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb7bbd5fbb64d0646a11fe1ab1882b15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9c2df5b3fe73cc54791749a805e37687
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
using UnityEngine;
namespace HurricaneVR.Framework.Weapons.Guns.PartFinders
{
public class HVRChamberedCasingFinder : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3ada3d5a28435ca42ab5cbc53dc7c2a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
using UnityEngine;
namespace HurricaneVR.Framework.Weapons.Guns.PartFinders
{
public class HVRChamberedRoundFinder : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b67ef4552bd2b1f49894e6ff773d67da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace HurricaneVR.Framework.Weapons.Guns.PartFinders
{
public class HVRMagazineFinder : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3ac97456e56d5c543861420a61ed719b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1366c90de78d471fb0da0dd5a440fe4b
timeCreated: 1604445095

View File

@@ -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();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bb5167cc14034676a2d0d91513d89cf3
timeCreated: 1604445111

View 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);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 85b4ee1a35cc4bb19411742b63218921
timeCreated: 1605976440

View 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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 83b3fda07db74abe982337dd671606de
timeCreated: 1605382407

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: af2a65f4bdd647958bec95376f37db27
timeCreated: 1606176025

View File

@@ -0,0 +1,7 @@
namespace HurricaneVR.Framework.Weapons
{
public class HVRShotgunMagazine : HVRAmmo
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ece64f546b4b471f9761a7aca682299f
timeCreated: 1606175343