Add bow and arrow

This commit is contained in:
Toomas Tamm
2021-02-04 21:31:13 +02:00
parent a9f341cd53
commit 577c0e75af
33 changed files with 2750 additions and 70 deletions

8
Assets/Scripts/Bow.meta Normal file
View File

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

102
Assets/Scripts/Bow/Arrow.cs Normal file
View File

@@ -0,0 +1,102 @@
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Arrow : XRGrabInteractable
{
public float speed = 2000.0f;
public Transform tip = null;
private bool _inAir = false;
private Vector3 _lastPosition = Vector3.zero;
private Rigidbody _rigidbody = null;
protected override void Awake()
{
base.Awake();
_rigidbody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
if (!_inAir) return;
CheckForCollision();
_lastPosition = tip.position;
}
private void CheckForCollision()
{
RaycastHit hit;
if (Physics.Linecast(_lastPosition, tip.position, out hit, LayerMask.GetMask("Default"),
QueryTriggerInteraction.Ignore))
{
Stop();
}
}
private void Stop()
{
_inAir = false;
SetPhysics(false);
}
public void Release(float pullValue)
{
_inAir = true;
SetPhysics(true);
MaskAndFire(pullValue);
StartCoroutine(RotateWithVelocity());
_lastPosition = tip.position;
}
private void SetPhysics(bool usePhysics)
{
_rigidbody.isKinematic = !usePhysics;
_rigidbody.useGravity = usePhysics;
}
private void MaskAndFire(float power)
{
colliders[0].enabled = false;
interactionLayerMask = 1 << LayerMask.NameToLayer("IgnoreInteraction");
Vector3 force = transform.forward * (power * speed);
_rigidbody.AddForce(force);
}
private IEnumerator RotateWithVelocity()
{
yield return new WaitForFixedUpdate();
while (_inAir)
{
Quaternion newRotation = Quaternion.LookRotation(_rigidbody.velocity, transform.up);
transform.rotation = newRotation;
yield return null;
}
}
public new void OnSelectEntered(XRBaseInteractor interactor)
{
base.OnSelectEntered(interactor);
}
public new void OnSelectExited(XRBaseInteractor interactor)
{
base.OnSelectExited(interactor);
}
public new void OnSelectExiting(XRBaseInteractor interactor)
{
base.OnSelectExiting(interactor);
}
}
}

View File

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

34
Assets/Scripts/Bow/Bow.cs Normal file
View File

@@ -0,0 +1,34 @@
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Bow : XRGrabInteractable
{
private Animator _animator = null;
private Puller _puller = null;
private static readonly int Blend = Animator.StringToHash("Blend");
protected override void Awake()
{
base.Awake();
_animator = GetComponent<Animator>();
_puller = GetComponentInChildren<Puller>();
}
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
base.ProcessInteractable(updatePhase);
if (updatePhase != XRInteractionUpdateOrder.UpdatePhase.Dynamic) return;
if (!isSelected) return;
AnimateBow(_puller.PullAmount);
}
private void AnimateBow(float value)
{
_animator.SetFloat(Blend, value);
}
}
}

View File

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

View File

@@ -0,0 +1,69 @@
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Notch : XRSocketInteractor
{
private Puller _puller = null;
private Arrow _currentArrow = null;
protected override void Awake()
{
base.Awake();
_puller = GetComponent<Puller>();
}
protected override void OnEnable()
{
base.OnEnable();
_puller.onSelectExited.AddListener(TryToReleaseArrow);
}
protected override void OnDisable()
{
base.OnDisable();
_puller.onSelectExited.RemoveListener(TryToReleaseArrow);
}
protected override void OnSelectEntered(XRBaseInteractable interactable)
{
base.OnSelectEntered(interactable);
StoreArrow(interactable);
}
private void StoreArrow(XRBaseInteractable interactable)
{
if (interactable is Arrow arrow)
{
_currentArrow = arrow;
}
}
private void TryToReleaseArrow(XRBaseInteractor interactor)
{
if (!_currentArrow) return;
ForceDeselect();
ReleaseArrow();
}
private void ForceDeselect()
{
_currentArrow.OnSelectExiting(this);
_currentArrow.OnSelectExited(this);
base.OnSelectExiting(_currentArrow);
base.OnSelectExited(_currentArrow);
}
private void ReleaseArrow()
{
_currentArrow.Release(_puller.PullAmount);
_currentArrow = null;
}
public override XRBaseInteractable.MovementType? selectedInteractableMovementTypeOverride =>
XRBaseInteractable.MovementType.Instantaneous;
}
}

View File

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

View File

@@ -0,0 +1,52 @@
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Puller : XRBaseInteractable
{
public float PullAmount { get; private set; } = 0.0f;
public Transform start = null;
public Transform end = null;
private XRBaseInteractor _pullingInteractor = null;
protected override void OnSelectEntered(XRBaseInteractor interactor)
{
base.OnSelectEntered(interactor);
_pullingInteractor = interactor;
}
protected override void OnSelectExited(XRBaseInteractor interactor)
{
base.OnSelectExited(interactor);
_pullingInteractor = null;
PullAmount = 0.0f;
}
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
base.ProcessInteractable(updatePhase);
if (updatePhase != XRInteractionUpdateOrder.UpdatePhase.Dynamic) return;
if (!isSelected) return;
Vector3 pullPosition = _pullingInteractor.transform.position;
PullAmount = CalculatePull(pullPosition);
}
private float CalculatePull(Vector3 pullPosition)
{
var startPosition = start.position;
Vector3 pullDirection = pullPosition - startPosition;
Vector3 targetDirection = end.position - startPosition;
float maxLength = targetDirection.magnitude;
targetDirection.Normalize();
float pullValue = Vector3.Dot(pullDirection, targetDirection) / maxLength;
return Mathf.Clamp(pullValue, 0, 1);
}
}
}

View File

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

View File

@@ -0,0 +1,51 @@
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Quiver : XRSocketInteractor
{
public GameObject arrowPrefab = null;
private Vector3 _attachOffset = Vector3.zero;
protected override void Awake()
{
base.Awake();
CreateAndSelectArrow();
SetAttachOffset();
}
protected override void OnSelectExited(XRBaseInteractable interactable)
{
base.OnSelectExited(interactable);
CreateAndSelectArrow();
}
private void CreateAndSelectArrow()
{
Arrow arrow = CreateArrow();
interactionManager.ForceSelect(this, arrow);
}
private Arrow CreateArrow()
{
var transform1 = transform;
GameObject arrowObject = Instantiate(arrowPrefab, transform1.position - _attachOffset, transform1.rotation);
return arrowObject.GetComponent<Arrow>();
}
private void SelectArrow(Arrow arrow)
{
OnSelectEntered(arrow);
arrow.OnSelectEntered(this);
}
private void SetAttachOffset()
{
if (selectTarget is XRGrabInteractable interactable)
{
_attachOffset = interactable.attachTransform.localPosition;
}
}
}
}

View File

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