deltavr multiplayer 2.0

This commit is contained in:
Toomas Tamm
2023-05-08 15:56:10 +03:00
parent 978809a002
commit 07b9b9e2f4
10937 changed files with 2968397 additions and 1521012 deletions

View File

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

View File

@@ -1,43 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace Audio
{
[CreateAssetMenu(menuName = "AudioClipGroup")]
public class AudioClipGroup : ScriptableObject
{
[Range(0, 2)] public float volumeMin = 1;
[Range(0, 2)] public float volumeMax = 1;
[Range(0, 2)] public float pitchMin = 1;
[Range(0, 2)] public float pitchMax = 1;
public float delay = 0.1f;
public List<AudioClip> audioClips;
private float _timestamp;
public void OnEnable()
{
_timestamp = 0;
}
public void Play()
{
if (AudioSourcePool.Instance == null) return;
Play(AudioSourcePool.Instance.GetAudioSource());
}
public void Play(AudioSource source)
{
if (audioClips.Count <= 0) return;
if (_timestamp > Time.time) return;
_timestamp = Time.time + delay;
source.volume = Random.Range(volumeMin, volumeMax);
source.pitch = Random.Range(pitchMin, pitchMax);
source.clip = audioClips[Random.Range(0, audioClips.Count)];
source.Play();
}
}
}

View File

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

View File

@@ -1,34 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace Audio
{
public class AudioSourcePool : MonoBehaviour
{
public static AudioSourcePool Instance;
public AudioSource audioSourcePrefab;
private List<AudioSource> _audioSources;
public void Awake()
{
Instance = this;
_audioSources = new List<AudioSource>();
}
public AudioSource GetAudioSource()
{
foreach (AudioSource source in _audioSources)
{
if (!source.isPlaying)
{
return source;
}
}
AudioSource newSource = Instantiate(audioSourcePrefab, this.transform);
_audioSources.Add(newSource);
return newSource;
}
}
}

View File

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

View File

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

View File

@@ -1,120 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using Photon.Pun;
using Random = UnityEngine.Random;
namespace Bow
{
public class ArcheryRange : MonoBehaviourPunCallbacks
{
public TMP_Text highScoreText;
public TMP_Text timeLeftText;
public TMP_Text scoreText;
public Transform targetStartPosition;
public Transform targetEndPosition;
public GameObject targetPrefab;
public StartTarget startTarget;
public Vector3 minRandomOffset = new Vector3(0f, -2f, -5f);
public Vector3 maxRandomOffset = new Vector3(0f, 2f, 5f);
public float roundLength = 60f;
public float targetSpawnTime = 3f;
private List<ArcheryTarget> _targets;
private float _score;
private float _maxScore;
private float _roundEndTime;
private float _nextTargetTime;
private float _startEndDistance;
private bool _roundActive;
// Start is called before the first frame update
void Start()
{
highScoreText.text = "High Score: 0";
_roundActive = false;
_targets = new List<ArcheryTarget>();
_score = 0;
_maxScore = 0;
_roundEndTime = 0f;
_startEndDistance = Vector3.Distance(targetStartPosition.position, targetEndPosition.position);
}
// Update is called once per frame
void Update()
{
if (!_roundActive) return;
if (Time.time >= _roundEndTime)
{
Reset();
}
else
{
timeLeftText.text = $"Time Left: {Math.Ceiling((_roundEndTime - Time.time) % 60)}";
if (Time.time >= _nextTargetTime)
{
_nextTargetTime = Time.time + targetSpawnTime;
SpawnTarget();
}
}
}
private void SpawnTarget()
{
var randomPos = targetStartPosition.position + new Vector3(
Random.Range(minRandomOffset.x, maxRandomOffset.x),
(float) Math.Round(Random.Range(minRandomOffset.y, maxRandomOffset.y)),
Random.Range(minRandomOffset.z, maxRandomOffset.z));
//var prefab = Instantiate(targetPrefab, randomPos, Quaternion.identity, null);
var prefab = PhotonNetwork.Instantiate("TargetUFO_Network", randomPos, Quaternion.identity);
ArcheryTarget target = prefab.GetComponent<ArcheryTarget>();
target.endPosition = targetEndPosition.position;
target.minRandomOffset = minRandomOffset;
target.maxRandomOffset = maxRandomOffset;
target.archeryRange = this;
_targets.Add(target);
}
public void Reset()
{
foreach (var target in _targets.Where(target => target != null))
{
//Destroy(target.gameObject);
PhotonNetwork.Destroy(target.gameObject.GetPhotonView());
}
_targets = new List<ArcheryTarget>();
if (_maxScore < _score) _maxScore = _score;
_score = 0;
highScoreText.text = $"High Score: {_maxScore}";
startTarget.ShowTarget();
_roundActive = false;
timeLeftText.text = "";
}
public void StartRound()
{
_roundEndTime = Time.time + roundLength;
_nextTargetTime = Time.time;
_roundActive = true;
}
public void AddScore(float distance)
{
_score += distance;
scoreText.text = $"Score: {_score}";
}
}
}

View File

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

View File

@@ -1,79 +0,0 @@
using System;
using UnityEngine;
using Photon.Pun;
using Random = UnityEngine.Random;
namespace Bow
{
public class ArcheryTarget : MonoBehaviourPun
{
public GameObject pointsText;
public Vector3 endPosition;
public float forwardSpeed = 2f;
public float sidewaysSpeed = 1f;
public ArcheryRange archeryRange;
public Vector3 minRandomOffset = new Vector3();
public Vector3 maxRandomOffset = new Vector3();
private bool _flipDirection;
private void Start()
{
_flipDirection = Random.value > 0.5f;
var position = transform.position;
minRandomOffset.z += position.z;
maxRandomOffset.z += position.z;
}
// Update is called once per frame
void Update()
{
float step = forwardSpeed * Time.deltaTime;
var position = transform.position;
if (Math.Abs(position.x - endPosition.x) < 0.1) Destroy(gameObject);
if (Math.Abs(position.z - maxRandomOffset.z) < 0.1)
{
_flipDirection = true;
}
if (Math.Abs(position.z - minRandomOffset.z) < 0.1)
{
_flipDirection = false;
}
float desiredZ = _flipDirection ? maxRandomOffset.z : minRandomOffset.z;
transform.position = Vector3.MoveTowards(position,
new Vector3(endPosition.x, position.y, desiredZ), step);
}
[PunRPC]
public void OnArrowHitPun()
{
var position = transform.position;
float score = (float) Math.Round(Vector3.Distance(position, endPosition));
archeryRange.AddScore(score);
GameObject prefab = Instantiate(pointsText, position, Quaternion.Euler(0, 90f, 0), null);
PointsText target = prefab.GetComponent<PointsText>();
target.SetPoints(score);
}
public void OnArrowHit(Arrow arrow)
{
if (arrow == null) return;
Destroy(arrow.gameObject);
photonView.RPC("OnArrowHitPun", RpcTarget.All);
PhotonNetwork.Destroy(photonView);
}
}
}

View File

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

View File

@@ -1,17 +0,0 @@
using UnityEngine;
namespace Bow
{
public class ArcheryTargetCollisionProxy : MonoBehaviour
{
public ArcheryTarget target;
public void OnArrowHit(Arrow arrow)
{
if (arrow == null) return;
if (target == null) return;
target.OnArrowHit(arrow);
}
}
}

View File

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

View File

@@ -1,124 +0,0 @@
using System;
using System.Collections;
using Audio;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Arrow : XRGrabInteractable
{
public AudioClipGroup hitSounds;
public float speed = 2000.0f;
public Transform tip = null;
public float maxLifetimeAfterShot = 60f;
private bool _inAir = false;
private Vector3 _lastPosition = Vector3.zero;
private Rigidbody _rigidbody = null;
private float _timeToDestroyOn;
protected override void Awake()
{
base.Awake();
_rigidbody = GetComponent<Rigidbody>();
_timeToDestroyOn = float.MaxValue;
}
private void FixedUpdate()
{
if (!_inAir) return;
CheckForCollision();
_lastPosition = tip.position;
if (_timeToDestroyOn <= Time.time)
{
Destroy(gameObject);
}
}
private void CheckForCollision()
{
RaycastHit hit;
if (Physics.Linecast(_lastPosition, tip.position, out hit, LayerMask.GetMask("Default"),
QueryTriggerInteraction.Ignore))
{
hit.collider.gameObject.SendMessage("OnArrowHit", this,
SendMessageOptions.DontRequireReceiver);
Stop();
hitSounds.Play();
}
}
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);
_timeToDestroyOn = Time.time + maxLifetimeAfterShot;
}
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);
}
protected override void OnDestroy()
{
base.OnDestroy();
colliders.Clear();
}
}
}

View File

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

View File

@@ -1,124 +0,0 @@
using System;
using System.Collections;
using Audio;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Arrow_Network : XRGrabInteractable
{
public AudioClipGroup hitSounds;
public float speed = 2000.0f;
public Transform tip = null;
public float maxLifetimeAfterShot = 60f;
private bool _inAir = false;
private Vector3 _lastPosition = Vector3.zero;
private Rigidbody _rigidbody = null;
private float _timeToDestroyOn;
protected override void Awake()
{
base.Awake();
_rigidbody = GetComponent<Rigidbody>();
_timeToDestroyOn = float.MaxValue;
}
private void FixedUpdate()
{
if (!_inAir) return;
CheckForCollision();
_lastPosition = tip.position;
if (_timeToDestroyOn <= Time.time)
{
Destroy(gameObject);
}
}
private void CheckForCollision()
{
RaycastHit hit;
if (Physics.Linecast(_lastPosition, tip.position, out hit, LayerMask.GetMask("Default"),
QueryTriggerInteraction.Ignore))
{
hit.collider.gameObject.SendMessage("OnArrowHit", this,
SendMessageOptions.DontRequireReceiver);
Stop();
hitSounds.Play();
}
}
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);
_timeToDestroyOn = Time.time + maxLifetimeAfterShot;
}
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);
}
protected override void OnDestroy()
{
base.OnDestroy();
colliders.Clear();
}
}
}

View File

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

View File

@@ -1,34 +0,0 @@
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

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

View File

@@ -1,72 +0,0 @@
using Audio;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Notch : XRSocketInteractor
{
public AudioClipGroup nockSounds;
public AudioClipGroup releaseSounds;
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)) return;
_currentArrow = arrow;
nockSounds.Play();
}
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;
releaseSounds.Play();
}
public override XRBaseInteractable.MovementType? selectedInteractableMovementTypeOverride =>
XRBaseInteractable.MovementType.Instantaneous;
}
}

View File

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

View File

@@ -1,37 +0,0 @@
using TMPro;
using UnityEngine;
namespace Bow
{
public class PointsText : MonoBehaviour
{
public TMP_Text text;
public float destroyTime = 2f;
public float upSpeed = 2f;
private float _destroyOnTime;
private void Start()
{
_destroyOnTime = Time.time + destroyTime;
}
public void Update()
{
if (_destroyOnTime <= Time.time)
{
Destroy(gameObject);
}
float step = upSpeed * Time.deltaTime;
var position = transform.position;
transform.position = Vector3.MoveTowards(position,
new Vector3(position.x, position.y + 1f, position.z), step);
}
public void SetPoints(float points)
{
text.text = $"+{points}";
}
}
}

View File

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

View File

@@ -1,68 +0,0 @@
using Audio;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace Bow
{
public class Puller : XRBaseInteractable
{
public float PullAmount { get; private set; } = 0.0f;
public AudioClipGroup pullSounds;
public AudioClipGroup maxPullSounds;
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;
float newPull = CalculatePull(pullPosition);
if (PullAmount == 0 & newPull > 0)
{
pullSounds.Play();
}
if (PullAmount < 0.98f & newPull >= 0.98f)
{
maxPullSounds.Play();
}
PullAmount = newPull;
}
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

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

View File

@@ -1,51 +0,0 @@
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

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

View File

@@ -1,59 +0,0 @@
using UnityEngine;
using Photon.Pun;
namespace Bow
{
public class StartTarget : MonoBehaviourPun
{
public ArcheryRange archeryRange;
public Canvas textCanvas;
private MeshRenderer _meshRenderer;
private BoxCollider _boxCollider;
// Start is called before the first frame update
void Start()
{
_meshRenderer = GetComponent<MeshRenderer>();
_boxCollider = GetComponent<BoxCollider>();
}
public void OnArrowHitPun()
{
HideTarget();
archeryRange.StartRound();
}
[PunRPC]
private void HideTargetPun()
{
_meshRenderer.enabled = false;
_boxCollider.enabled = false;
textCanvas.enabled = false;
}
[PunRPC]
public void ShowTargetPun()
{
_meshRenderer.enabled = true;
_boxCollider.enabled = true;
textCanvas.enabled = true;
}
public void OnArrowHit(Arrow arrow)
{
if (arrow == null) return;
Destroy(arrow.gameObject);
OnArrowHitPun();
}
private void HideTarget()
{
photonView.RPC("HideTargetPun", RpcTarget.AllBuffered);
}
public void ShowTarget()
{
photonView.RPC("ShowTargetPun", RpcTarget.AllBuffered);
}
}
}

View File

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

View File

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

View File

@@ -1,93 +0,0 @@
using System;
using System.Collections;
using Oculus.Platform.Models;
using UnityEngine;
using UnityEngine.Assertions.Must;
using Random = UnityEngine.Random;
namespace Breakout
{
public class BreakableCube : MonoBehaviour
{
public Vector3 speed;
public bool spawnBall;
public GameObject ballPrefab;
public float fadeTime = 2f;
private bool _hasSpawnedBall;
private static readonly int Dissolve = Shader.PropertyToID("Vector1_b97048ce40a9495091dbb3eb2c84769e"); // From Dissolve Shader Graph
private void Awake()
{
Events.OnBreakoutEndGame += EventDestroyCube;
Events.OnBreakoutSetSpeed += SetSpeed;
_hasSpawnedBall = false;
}
private void EventDestroyCube()
{
DestroyCube(false);
}
private void OnDestroy()
{
Events.OnBreakoutEndGame -= EventDestroyCube;
Events.OnBreakoutSetSpeed -= SetSpeed;
}
private void Update()
{
transform.position += (speed * Time.deltaTime);
}
private void OnCollisionEnter(Collision other)
{
BreakoutBall ball = other.gameObject.GetComponent<BreakoutBall>();
if (ball == null) return;
DestroyCube(true);
}
private void DestroyCube(bool allowBallSpawn)
{
if (spawnBall & !_hasSpawnedBall & allowBallSpawn)
{
_hasSpawnedBall = true;
var ball = Instantiate(ballPrefab, transform.position, Quaternion.identity, null);
ball.GetComponent<Rigidbody>().AddForce(
new Vector3(
Random.Range(-2.0f, 2.0f),
Random.Range(-2.0f, 2.0f),
Random.Range(-2.0f, 2.0f)
));
Events.AddBalls();
}
speed.x = 0;
StartCoroutine(FadeMaterial(GetComponent<MeshRenderer>().material, fadeTime));
//Destroy(gameObject, Time.maximumDeltaTime);
}
private void SetSpeed(float newspeed)
{
speed.x = newspeed;
}
private IEnumerator FadeMaterial(Material material, float fadeTime)
{
while (material.GetFloat(Dissolve) < 0.9)
{
var newDissolve = Mathf.MoveTowards(material.GetFloat(Dissolve), 1, fadeTime * Time.deltaTime);
material.SetFloat(Dissolve, newDissolve);
yield return null;
}
Destroy(gameObject);
}
}
}

View File

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

View File

@@ -1,49 +0,0 @@
using System;
using UnityEngine;
namespace Breakout
{
public class BreakoutBall : MonoBehaviour
{
public float speed = 2f;
private Rigidbody _rigidbody;
private void Awake()
{
Events.OnBreakoutEndGame += DestroyBall;
}
private void OnDestroy()
{
Events.OnBreakoutEndGame -= DestroyBall;
}
private void Start()
{
_rigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
// Fix velocity on X axis so ball is more predictable.
var velocity = _rigidbody.velocity;
velocity.x = Math.Sign(velocity.x) * speed;
velocity = velocity.normalized * (speed * 1.5f);
_rigidbody.velocity = velocity;
}
private void DestroyBall()
{
Destroy(gameObject);
}
private void OnCollisionEnter(Collision other)
{
KinematicSpeedTransfer kst = other.gameObject.GetComponent<KinematicSpeedTransfer>();
if (kst == null) return;
Events.BreakoutStartGame();
}
}
}

View File

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

View File

@@ -1,132 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Breakout;
using Unity.Mathematics;
using UnityEngine;
using Photon.Pun;
using Random = UnityEngine.Random;
public class BreakoutManager : MonoBehaviourPunCallbacks
{
public GameObject defaultBreakablePrefab;
public GameObject extraBallBreakablePrefab;
public GameObject startBallSpawnPoint;
public GameObject ballPrefab;
public List<Transform> spawnPoints;
public float timeBetweenRows = 5f;
public float startRowSpeed = 0.15f;
//private float _speedIncreasePerRow = 0.01f;
public float extraBallBreakableChance = 0.1f;
private float _nextRowTime;
private float _currentRowSpeed;
private int _ballCount;
private bool _gameStarted;
private void Awake()
{
_gameStarted = false;
_ballCount = 1;
_nextRowTime = Time.time;
_currentRowSpeed = startRowSpeed;
Events.OnBreakoutEndGame += EndGame;
Events.OnBreakoutStartGame += StartGame;
Events.OnBreakoutReduceBalls += ReduceBalls;
Events.OnBreakoutAddBalls += AddBalls;
}
void OnDestroy()
{
Events.OnBreakoutEndGame -= EndGame;
Events.OnBreakoutStartGame -= StartGame;
Events.OnBreakoutReduceBalls -= ReduceBalls;
Events.OnBreakoutAddBalls -= AddBalls;
}
void Update()
{
if (!_gameStarted) return;
if (_nextRowTime < Time.time)
{
SpawnRow();
}
}
void StartGame()
{
if (_gameStarted) return;
_gameStarted = true;
_nextRowTime = Time.time;
}
private void SpawnBall()
{
PhotonNetwork.Instantiate("Ball_Network", startBallSpawnPoint.transform.position, Quaternion.identity);
//Instantiate(ballPrefab, startBallSpawnPoint.transform.position, Quaternion.identity, null);
_ballCount += 1;
}
void EndGame()
{
if (!_gameStarted) return;
_gameStarted = false;
SpawnBall();
_ballCount = 1;
}
void SpawnRow()
{
_nextRowTime = Time.time + timeBetweenRows;
//currentRowSpeed += speedIncreasePerRow;
foreach (var point in spawnPoints)
{
GameObject box;
if (Random.value <= extraBallBreakableChance)
{
box = PhotonNetwork.Instantiate("Breakable Cube Extra Ball_Network", point.position, Quaternion.identity);
//box = Instantiate(extraBallBreakablePrefab, point.position, Quaternion.identity, null);
}
else
{
box = PhotonNetwork.Instantiate("Breakable Cube_Network", point.position, Quaternion.identity);
//box = Instantiate(defaultBreakablePrefab, point.position, Quaternion.identity, null);
}
var cube = box.GetComponent<BreakableCube>();
cube.speed.x = _currentRowSpeed;
}
Events.BreakoutSetSpeed(_currentRowSpeed);
}
void ReduceBalls()
{
_ballCount -= 1;
if (_ballCount <= 0)
{
Events.BreakoutEndGame();
}
}
void AddBalls()
{
_ballCount += 1;
}
}

View File

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

View File

@@ -1,16 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using Breakout;
using UnityEngine;
public class DestroyBallForcefield : MonoBehaviour
{
private void OnCollisionEnter(Collision other)
{
BreakoutBall ball = other.gameObject.GetComponent<BreakoutBall>();
if (ball == null) return;
Events.ReduceBalls();
Destroy(ball.gameObject);
}
}

View File

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

View File

@@ -1,17 +0,0 @@
using UnityEngine;
namespace Breakout
{
public class EndForcefield : MonoBehaviour
{
private void OnCollisionEnter(Collision other)
{
BreakableCube breakableCube = other.gameObject.GetComponent<BreakableCube>();
if (breakableCube != null)
{
Events.BreakoutEndGame();
}
}
}
}

View File

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

View File

@@ -1,35 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KinematicSpeedTransfer : MonoBehaviour
{
public float amplification = 1f;
private Vector3 _oldPosition;
private Vector3 _velocity;
// Start is called before the first frame update
void Start()
{
_oldPosition = transform.position;
_velocity = Vector3.zero;
}
// Update is called once per frame
void Update()
{
Vector3 newPosition = transform.position;
Vector3 posDiff = newPosition - _oldPosition;
_velocity = posDiff / Time.deltaTime;
_oldPosition = newPosition;
}
private void OnCollisionEnter(Collision other)
{
if (other.rigidbody.isKinematic) return;
other.rigidbody.AddRelativeForce(_velocity * amplification, ForceMode.Impulse);
}
}

View File

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

View File

@@ -1,33 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class OffsetOnDirectHit : MonoBehaviour
{
public float minAngle = 0;
public float maxAngle = 20;
private Rigidbody _rigidbody;
private void Start()
{
_rigidbody = new Rigidbody();
}
private void OnCollisionEnter(Collision other)
{
Vector3 normal = other.contacts[0].normal;
Vector3 velocity = _rigidbody.velocity;
// Get Angle
float angle = Vector3.Angle(velocity, -normal);
if (angle > minAngle & angle < maxAngle)
{
// Add random torque to randomize direction
_rigidbody.AddTorque(new Vector3(Random.Range(0, 1f), Random.Range(0, 1f), Random.Range(0, 1f)));
}
}
}

View File

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

View File

@@ -1,20 +0,0 @@
using System;
public static class Events
{
public static event Action OnBreakoutEndGame;
public static void BreakoutEndGame() => OnBreakoutEndGame?.Invoke();
public static event Action OnBreakoutStartGame;
public static void BreakoutStartGame() => OnBreakoutStartGame?.Invoke();
public static event Action<float> OnBreakoutSetSpeed;
public static void BreakoutSetSpeed(float speed) => OnBreakoutSetSpeed?.Invoke(speed);
public static event Action OnBreakoutReduceBalls;
public static void ReduceBalls() => OnBreakoutReduceBalls?.Invoke();
public static event Action OnBreakoutAddBalls;
public static void AddBalls() => OnBreakoutAddBalls?.Invoke();
}

View File

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

View File

@@ -1,44 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Poster : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Vector2[] uvSingleFace = {
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1),
new Vector2(-1, -1)
};
GetComponent<MeshFilter>().mesh.uv = uvSingleFace;
}
}

View File

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

View File

@@ -1 +0,0 @@
C# scripts, shaders etc go here.

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: b2eba341b0ca0ae49889cc9ba59875eb
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -1,22 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NavPoint : MonoBehaviour
{
public NavPoint previous;
public NavPoint next;
public NavPoint GetNext()
{
return next;
}
void OnDrawGizmos()
{
if (next == null) return;
Gizmos.color = Color.yellow;
Gizmos.DrawLine(transform.position, next.transform.position);
}
}

View File

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

View File

@@ -1,41 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
public class NavPointFollower : MonoBehaviour
{
public NavPoint startNavPoint;
public float rotationSpeed = 1f;
public float speed = 1f;
private Rigidbody _rigidbody;
private void Start()
{
_rigidbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
var transform1 = transform;
var position = transform1.position;
_rigidbody.MovePosition(position + transform1.forward * (speed * Time.deltaTime));
var direction = (startNavPoint.transform.position - position).normalized;
direction.y = 0;
var lookRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * rotationSpeed);
if (Vector3.Distance(transform.position, startNavPoint.transform.position) < 0.3f)
{
startNavPoint = startNavPoint.GetNext();
}
}
}

View File

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

View File

@@ -1,32 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RGB : MonoBehaviour
{
public float colorChangeInterval = 2f;
public float minColor = 0;
public float maxColor = 100;
private Light _light;
private float _nextColorChange;
// Start is called before the first frame update
void Start()
{
_light = GetComponent<Light>();
_nextColorChange = Time.time;
}
// Update is called once per frame
void Update()
{
if (!(_nextColorChange <= Time.time)) return;
var r = Random.Range(minColor, maxColor);
var g = Random.Range(minColor, maxColor);
var b = Random.Range(minColor, maxColor);
_light.color = new Color(r, g, b);
_nextColorChange = Time.time + colorChangeInterval;
}
}

View File

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

View File

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

View File

@@ -1,626 +0,0 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.InputSystem;
using UnityEngine.Serialization;
/// <summary>
/// Use this class to map input actions to each controller state (mode)
/// and set up the transitions between controller states (modes).
/// </summary>
[AddComponentMenu("XR/Action Based Controller Manager")]
[DefaultExecutionOrder(kControllerManagerUpdateOrder)]
public class ActionBasedControllerManager : MonoBehaviour
{
public const int kControllerManagerUpdateOrder = 10;
public enum StateId
{
None,
Select,
Teleport,
Interact,
}
[Serializable]
public class StateEnterEvent : UnityEvent<StateId>
{
}
[Serializable]
public class StateUpdateEvent : UnityEvent
{
}
[Serializable]
public class StateExitEvent : UnityEvent<StateId>
{
}
/// <summary>
/// Use this class to create a controller state and set up its enter, update, and exit events.
/// </summary>
[Serializable]
public class ControllerState
{
[SerializeField]
[Tooltip("Sets the controller state to be active. " +
"For the default states, setting this value to true will automatically update their StateUpdateEvent.")]
bool m_Enabled;
/// <summary>
/// Sets the controller state to be active.
/// For the default states, setting this value to true will automatically update their <see cref="StateUpdateEvent"/>.
/// </summary>
public bool enabled
{
get => m_Enabled;
set => m_Enabled = value;
}
[SerializeField] [HideInInspector] StateId m_Id;
/// <summary>
/// Sets the identifier of the <see cref="ControllerState"/> from all the optional Controller States that the <see cref="ActionBasedControllerManager"/> holds.
/// </summary>
public StateId id
{
get => m_Id;
set => m_Id = value;
}
[SerializeField] StateEnterEvent m_OnEnter = new StateEnterEvent();
/// <summary>
/// The <see cref="StateEnterEvent"/> that will be invoked when entering the controller state.
/// </summary>
public StateEnterEvent onEnter
{
get => m_OnEnter;
set => m_OnEnter = value;
}
[SerializeField] StateUpdateEvent m_OnUpdate = new StateUpdateEvent();
/// <summary>
/// The <see cref="StateUpdateEvent"/> that will be invoked when updating the controller state.
/// </summary>
public StateUpdateEvent onUpdate
{
get => m_OnUpdate;
set => m_OnUpdate = value;
}
[SerializeField] StateExitEvent m_OnExit = new StateExitEvent();
/// <summary>
/// The <see cref="StateExitEvent"/> that will be invoked when exiting the controller state.
/// </summary>
public StateExitEvent onExit
{
get => m_OnExit;
set => m_OnExit = value;
}
public ControllerState(StateId defaultId = StateId.None) => this.id = defaultId;
}
[Space]
[Header("Controller GameObjects")]
[SerializeField, FormerlySerializedAs("m_BaseControllerGO")]
[Tooltip(
"The base controller GameObject, used for changing default settings on its components during state transitions.")]
GameObject m_BaseControllerGameObject;
/// <summary>
/// The base controller <see cref="GameObject"/>, used for changing default settings on its components during state transitions.
/// </summary>
public GameObject baseControllerGameObject
{
get => m_BaseControllerGameObject;
set => m_BaseControllerGameObject = value;
}
[SerializeField, FormerlySerializedAs("m_TeleportControllerGO")]
[Tooltip(
"The teleport controller GameObject, used for changing default settings on its components during state transitions.")]
GameObject m_TeleportControllerGameObject;
/// <summary>
/// The teleport controller <see cref="GameObject"/>, used for changing default settings on its components during state transitions.
/// </summary>
public GameObject teleportControllerGameObject
{
get => m_TeleportControllerGameObject;
set => m_TeleportControllerGameObject = value;
}
[Space]
[Header("Controller Actions")]
// State transition actions
[SerializeField]
[Tooltip("The reference to the action of activating the teleport mode for this controller.")]
InputActionReference m_TeleportModeActivate;
/// <summary>
/// The reference to the action of activating the teleport mode for this controller."
/// </summary>
public InputActionReference teleportModeActivate
{
get => m_TeleportModeActivate;
set => m_TeleportModeActivate = value;
}
// State transition actions
[SerializeField] [Tooltip("The reference to the action of listening to teleport actions.")]
InputActionReference m_NagivationModifier;
/// <summary>
/// The reference to the action of activating the teleport mode for this controller."
/// </summary>
public InputActionReference navigationModifier
{
get => m_NagivationModifier;
set => m_NagivationModifier = value;
}
[SerializeField] [Tooltip("The reference to the action of canceling the teleport mode for this controller.")]
InputActionReference m_TeleportModeCancel;
/// <summary>
/// The reference to the action of canceling the teleport mode for this controller."
/// </summary>
public InputActionReference teleportModeCancel
{
get => m_TeleportModeCancel;
set => m_TeleportModeCancel = value;
}
// Character movement actions
[SerializeField] [Tooltip("The reference to the action of turning the XR rig with this controller.")]
InputActionReference m_Turn;
/// <summary>
/// The reference to the action of turning the XR rig with this controller.
/// </summary>
public InputActionReference turn
{
get => m_Turn;
set => m_Turn = value;
}
[SerializeField] [Tooltip("The reference to the action of moving the XR rig with this controller.")]
InputActionReference m_Move;
/// <summary>
/// The reference to the action of moving the XR rig with this controller.
/// </summary>
public InputActionReference move
{
get => m_Move;
set => m_Move = value;
}
// Object control actions
[SerializeField, FormerlySerializedAs("m_TranslateObject")]
[Tooltip("The reference to the action of translating the selected object of this controller.")]
InputActionReference m_TranslateAnchor;
/// <summary>
/// The reference to the action of translating the selected object of this controller.
/// </summary>
public InputActionReference translateAnchor
{
get => m_TranslateAnchor;
set => m_TranslateAnchor = value;
}
[SerializeField, FormerlySerializedAs("m_RotateObject")]
[Tooltip("The reference to the action of rotating the selected object of this controller.")]
InputActionReference m_RotateAnchor;
/// <summary>
/// The reference to the action of rotating the selected object of this controller.
/// </summary>
public InputActionReference rotateAnchor
{
get => m_RotateAnchor;
set => m_RotateAnchor = value;
}
[Space]
[Header("Default States")]
#pragma warning disable IDE0044 // Add readonly modifier -- readonly fields cannot be serialized by Unity
[SerializeField]
[Tooltip("The default Select state and events for the controller.")]
ControllerState m_SelectState = new ControllerState(StateId.Select);
/// <summary>
/// (Read Only) The default Select state.
/// </summary>
public ControllerState selectState => m_SelectState;
[SerializeField] [Tooltip("The default Teleport state and events for the controller.")]
ControllerState m_TeleportState = new ControllerState(StateId.Teleport);
/// <summary>
/// (Read Only) The default Teleport state.
/// </summary>
public ControllerState teleportState => m_TeleportState;
[SerializeField] [Tooltip("The default Interact state and events for the controller.")]
ControllerState m_InteractState = new ControllerState(StateId.Interact);
/// <summary>
/// (Read Only) The default Interact state.
/// </summary>
public ControllerState interactState => m_InteractState;
#pragma warning restore IDE0044
// The list to store and run the default states
readonly List<ControllerState> m_DefaultStates = new List<ControllerState>();
// Components of the controller to switch on and off for different states
XRBaseController m_BaseController;
XRBaseInteractor m_BaseInteractor;
XRInteractorLineVisual m_BaseLineVisual;
XRBaseController m_TeleportController;
XRBaseInteractor m_TeleportInteractor;
XRInteractorLineVisual m_TeleportLineVisual;
protected void OnEnable()
{
FindBaseControllerComponents();
FindTeleportControllerComponents();
// Add default state events.
m_SelectState.onEnter.AddListener(OnEnterSelectState);
m_SelectState.onUpdate.AddListener(OnUpdateSelectState);
m_SelectState.onExit.AddListener(OnExitSelectState);
m_TeleportState.onEnter.AddListener(OnEnterTeleportState);
m_TeleportState.onUpdate.AddListener(OnUpdateTeleportState);
m_TeleportState.onExit.AddListener(OnExitTeleportState);
m_InteractState.onEnter.AddListener(OnEnterInteractState);
m_InteractState.onUpdate.AddListener(OnUpdateInteractState);
m_InteractState.onExit.AddListener(OnExitInteractState);
}
protected void OnDisable()
{
// Remove default state events.
m_SelectState.onEnter.RemoveListener(OnEnterSelectState);
m_SelectState.onUpdate.RemoveListener(OnUpdateSelectState);
m_SelectState.onExit.RemoveListener(OnExitSelectState);
m_TeleportState.onEnter.RemoveListener(OnEnterTeleportState);
m_TeleportState.onUpdate.RemoveListener(OnUpdateTeleportState);
m_TeleportState.onExit.RemoveListener(OnExitTeleportState);
m_InteractState.onEnter.RemoveListener(OnEnterInteractState);
m_InteractState.onUpdate.RemoveListener(OnUpdateInteractState);
m_InteractState.onExit.RemoveListener(OnExitInteractState);
}
// Start is called before the first frame update
protected void Start()
{
// Add states to the list
m_DefaultStates.Add(m_SelectState);
m_DefaultStates.Add(m_TeleportState);
m_DefaultStates.Add(m_InteractState);
// Initialize to start in m_SelectState
TransitionState(null, m_SelectState);
}
// Update is called once per frame
protected void Update()
{
foreach (var state in m_DefaultStates)
{
if (state.enabled)
{
state.onUpdate.Invoke();
return;
}
}
}
void TransitionState(ControllerState fromState, ControllerState toState)
{
if (fromState != null)
{
fromState.enabled = false;
fromState.onExit.Invoke(toState?.id ?? StateId.None);
}
if (toState != null)
{
toState.onEnter.Invoke(fromState?.id ?? StateId.None);
toState.enabled = true;
}
}
void FindBaseControllerComponents()
{
if (m_BaseControllerGameObject == null)
{
Debug.LogWarning("Missing reference to Base Controller GameObject.", this);
return;
}
if (m_BaseController == null)
{
m_BaseController = m_BaseControllerGameObject.GetComponent<XRBaseController>();
if (m_BaseController == null)
Debug.LogWarning(
$"Cannot find any {nameof(XRBaseController)} component on the Base Controller GameObject.", this);
}
if (m_BaseInteractor == null)
{
m_BaseInteractor = m_BaseControllerGameObject.GetComponent<XRBaseInteractor>();
if (m_BaseInteractor == null)
Debug.LogWarning(
$"Cannot find any {nameof(XRBaseInteractor)} component on the Base Controller GameObject.", this);
}
// Only check the line visual component for RayInteractor, since DirectInteractor does not use the line visual component
if (m_BaseInteractor is XRRayInteractor && m_BaseLineVisual == null)
{
m_BaseLineVisual = m_BaseControllerGameObject.GetComponent<XRInteractorLineVisual>();
if (m_BaseLineVisual == null)
Debug.LogWarning(
$"Cannot find any {nameof(XRInteractorLineVisual)} component on the Base Controller GameObject.",
this);
}
}
void FindTeleportControllerComponents()
{
if (m_TeleportControllerGameObject == null)
{
Debug.LogWarning("Missing reference to the Teleport Controller GameObject.", this);
return;
}
if (m_TeleportController == null)
{
m_TeleportController = m_TeleportControllerGameObject.GetComponent<XRBaseController>();
if (m_TeleportController == null)
Debug.LogWarning(
$"Cannot find {nameof(XRBaseController)} component on the Teleport Controller GameObject.", this);
}
if (m_TeleportLineVisual == null)
{
m_TeleportLineVisual = m_TeleportControllerGameObject.GetComponent<XRInteractorLineVisual>();
if (m_TeleportLineVisual == null)
Debug.LogWarning(
$"Cannot find {nameof(XRInteractorLineVisual)} component on the Teleport Controller GameObject.",
this);
}
if (m_TeleportInteractor == null)
{
m_TeleportInteractor = m_TeleportControllerGameObject.GetComponent<XRRayInteractor>();
if (m_TeleportInteractor == null)
Debug.LogWarning(
$"Cannot find {nameof(XRRayInteractor)} component on the Teleport Controller GameObject.", this);
}
}
/// <summary>
/// Find and configure the components on the base controller.
/// </summary>
/// <param name="enable"> Set it true to enable the base controller, false to disable it. </param>
void SetBaseController(bool enable)
{
FindBaseControllerComponents();
if (m_BaseController != null)
m_BaseController.enableInputActions = enable;
if (m_BaseInteractor != null)
m_BaseInteractor.enabled = enable;
if (m_BaseInteractor is XRRayInteractor && m_BaseLineVisual != null)
m_BaseLineVisual.enabled = enable;
}
/// <summary>
/// Find and configure the components on the teleport controller.
/// </summary>
/// <param name="enable"> Set it true to enable the teleport controller, false to disable it. </param>
void SetTeleportController(bool enable)
{
FindTeleportControllerComponents();
if (m_TeleportLineVisual != null)
m_TeleportLineVisual.enabled = enable;
if (m_TeleportController != null)
m_TeleportController.enableInputActions = enable;
if (m_TeleportInteractor != null)
m_TeleportInteractor.enabled = enable;
}
void OnEnterSelectState(StateId previousStateId)
{
// Change controller and enable actions depending on the previous state
switch (previousStateId)
{
case StateId.None:
// Enable transitions to Teleport state
EnableAction(m_TeleportModeActivate);
EnableAction(m_TeleportModeCancel);
EnableAction(m_NagivationModifier);
// Enable turn and move actions
EnableAction(m_Turn);
EnableAction(m_Move);
// Enable base controller components
SetBaseController(true);
break;
case StateId.Select:
break;
case StateId.Teleport:
EnableAction(m_Turn);
EnableAction(m_Move);
SetBaseController(true);
break;
case StateId.Interact:
EnableAction(m_Turn);
EnableAction(m_Move);
break;
default:
Debug.Assert(false, $"Unhandled case when entering Select from {previousStateId}.");
break;
}
}
void OnExitSelectState(StateId nextStateId)
{
// Change controller and disable actions depending on the next state
switch (nextStateId)
{
case StateId.None:
break;
case StateId.Select:
break;
case StateId.Teleport:
DisableAction(m_Turn);
DisableAction(m_Move);
SetBaseController(false);
break;
case StateId.Interact:
DisableAction(m_Turn);
DisableAction(m_Move);
break;
default:
Debug.Assert(false, $"Unhandled case when exiting Select to {nextStateId}.");
break;
}
}
void OnEnterTeleportState(StateId previousStateId) => SetTeleportController(true);
void OnExitTeleportState(StateId nextStateId) => SetTeleportController(false);
void OnEnterInteractState(StateId previousStateId)
{
// Enable object control actions
EnableAction(m_TranslateAnchor);
EnableAction(m_RotateAnchor);
}
void OnExitInteractState(StateId nextStateId)
{
// Disable object control actions
DisableAction(m_TranslateAnchor);
DisableAction(m_RotateAnchor);
}
/// <summary>
/// This method is automatically called each frame to handle initiating transitions out of the Select state.
/// </summary>
void OnUpdateSelectState()
{
// Transition from Select state to Teleport state when the user triggers the "Teleport Mode Activate" action but not the "Cancel Teleport" action
var teleportModeAction = GetInputAction(m_TeleportModeActivate);
var cancelTeleportModeAction = GetInputAction(m_TeleportModeCancel);
var allowNavigationAction = GetInputAction(m_NagivationModifier);
var triggerTeleportMode = teleportModeAction != null && teleportModeAction.IsPressed();
var cancelTeleport = cancelTeleportModeAction != null && cancelTeleportModeAction.IsPressed();
var allowNavigation = allowNavigationAction != null && allowNavigationAction.IsPressed();
#region Check if teleport vector is north
Vector2 teleportAxis = teleportModeAction.ReadValue<Vector2>();
bool isNorth = teleportAxis.y > 0.8;
#endregion
if (triggerTeleportMode && !cancelTeleport && allowNavigation && isNorth)
{
TransitionState(m_SelectState, m_TeleportState);
return;
}
// Transition from Select state to Interact state when the interactor has a selectTarget
FindBaseControllerComponents();
if (m_BaseInteractor.selectTarget != null)
TransitionState(m_SelectState, m_InteractState);
}
/// <summary>
/// Updated every frame to handle the transition to m_SelectState state.
/// </summary>
void OnUpdateTeleportState()
{
// Transition from Teleport state to Select state when we release the Teleport trigger or cancel Teleport mode
var teleportModeAction = GetInputAction(m_TeleportModeActivate);
var cancelTeleportModeAction = GetInputAction(m_TeleportModeCancel);
var allowNavigationAction = GetInputAction(m_NagivationModifier);
var cancelTeleport = cancelTeleportModeAction != null && cancelTeleportModeAction.triggered;
var releasedTeleport = teleportModeAction != null && teleportModeAction.phase == InputActionPhase.Waiting;
var allowNavigation = allowNavigationAction != null && allowNavigationAction.IsPressed();
if (cancelTeleport || releasedTeleport || !allowNavigation)
{
if (!cancelTeleport)
{
// Force teleportation
XRRayInteractor interactor = m_TeleportControllerGameObject.GetComponent<XRRayInteractor>();
if (interactor.selectTarget != null)
interactor.interactionManager.ForceSelect(interactor, interactor.selectTarget);
}
TransitionState(m_TeleportState, m_SelectState);
}
}
void OnUpdateInteractState()
{
// Transition from Interact state to Select state when the base interactor no longer has a select target
if (m_BaseInteractor.selectTarget == null)
TransitionState(m_InteractState, m_SelectState);
}
static void EnableAction(InputActionReference actionReference)
{
var action = GetInputAction(actionReference);
if (action != null && !action.enabled)
action.Enable();
}
static void DisableAction(InputActionReference actionReference)
{
var action = GetInputAction(actionReference);
if (action != null && action.enabled)
action.Disable();
}
static InputAction GetInputAction(InputActionReference actionReference)
{
#pragma warning disable IDE0031 // Use null propagation -- Do not use for UnityEngine.Object types
return actionReference != null ? actionReference.action : null;
#pragma warning restore IDE0031
}
}

View File

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

View File

@@ -1,37 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Inputs;
public class CustomSnapTurnProvider : ActionBasedSnapTurnProvider
{
[SerializeField]
[Tooltip("The Input System Action that will be used to read Snap Turn data from the left hand controller. Must be a Value Vector2 Control.")]
InputActionProperty m_allowNavigation;
/// <summary>
/// The Input System Action that will be used to read Snap Turn data sent from the left hand controller. Must be a <see cref="InputActionType.Value"/> <see cref="Vector2Control"/> Control.
/// </summary>
public InputActionProperty allowNavigation
{
get => m_allowNavigation;
set => SetInputActionProperty(ref m_allowNavigation, value);
}
void SetInputActionProperty(ref InputActionProperty property, InputActionProperty value)
{
if (Application.isPlaying)
property.DisableDirectAction();
property = value;
if (Application.isPlaying && isActiveAndEnabled)
property.EnableDirectAction();
}
protected override Vector2 ReadInput()
{
return m_allowNavigation.action.IsPressed() ? base.ReadInput() : Vector2.zero;
}
}

View File

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

View File

@@ -1,80 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
namespace UnityXR
{
public class HandPresence : MonoBehaviour
{
public bool showController = false;
public InputDeviceCharacteristics controllerCharacteristics;
public List<GameObject> controllerPrefabs;
public GameObject handModelPrefab;
private InputDevice _targetDevice;
private GameObject _spawnedController;
private GameObject _spawnedHandModel;
private Animator _handAnimator;
private static readonly int Trigger = Animator.StringToHash("Trigger");
private static readonly int Grip = Animator.StringToHash("Grip");
private void TryInitialize()
{
var devices = new List<InputDevice>();
InputDevices.GetDevicesWithCharacteristics(controllerCharacteristics, devices);
if (devices.Count <= 0) return;
_targetDevice = devices[0];
GameObject prefab = controllerPrefabs.Find(controller => controller.name == _targetDevice.name);
_spawnedController = Instantiate(prefab ? prefab : controllerPrefabs[0], transform);
_spawnedHandModel = Instantiate(handModelPrefab, transform);
_handAnimator = _spawnedHandModel.GetComponent<Animator>();
}
private void UpdateHandAnimation()
{
if (_targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue))
{
_handAnimator.SetFloat(Trigger, triggerValue);
}
else
{
_handAnimator.SetFloat(Trigger, 0);
}
if (_targetDevice.TryGetFeatureValue(CommonUsages.grip, out float gripValue))
{
_handAnimator.SetFloat(Grip, gripValue);
}
else
{
_handAnimator.SetFloat(Grip, 0);
}
}
// Update is called once per frame
void Update()
{
if (!_targetDevice.isValid)
{
TryInitialize();
}
else
{
if (showController)
{
_spawnedHandModel.SetActive(false);
_spawnedController.SetActive(true);
}
else
{
_spawnedHandModel.SetActive(true);
_spawnedController.SetActive(false);
UpdateHandAnimation();
}
}
}
}
}

View File

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

View File

@@ -1,18 +0,0 @@
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
namespace UnityXR
{
public class TeleportWorldArea : TeleportationArea
{
// Override the teleport request to use the world rotation and not our gameObject's transform
protected override bool GenerateTeleportRequest(XRBaseInteractor interactor, RaycastHit raycastHit,
ref TeleportRequest teleportRequest)
{
teleportRequest.destinationPosition = raycastHit.point;
teleportRequest.matchOrientation = MatchOrientation.WorldSpaceUp; // use the area transform for data.
teleportRequest.destinationRotation = Quaternion.identity;
return true;
}
}
}

View File

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

View File

@@ -1,26 +0,0 @@
using UnityEngine.XR.Interaction.Toolkit;
public class XRGrabVelocityTracked : XRGrabInteractable
{
protected override void OnSelectEntered(XRBaseInteractor interactor)
{
SetParentToXRRig();
base.OnSelectEntered(interactor);
}
protected override void OnSelectExited(XRBaseInteractor interactor)
{
SetParentToWorld();
base.OnSelectExited(interactor);
}
public void SetParentToXRRig()
{
transform.SetParent(selectingInteractor.transform);
}
public void SetParentToWorld()
{
transform.SetParent(null);
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c96c5d5e9ecc35d4b8732d567d0c8458
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

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