Initial commit
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
namespace XRMultiplayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a projectile in the game.
|
||||
/// </summary>
|
||||
public class Projectile : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The trail renderer for the projectile.
|
||||
/// </summary>
|
||||
[SerializeField] protected TrailRenderer m_TrailRenderer;
|
||||
|
||||
[SerializeField] protected float m_Lifetime = 10.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The previous position of the projectile.
|
||||
/// </summary>
|
||||
Vector3 m_PrevPos = Vector3.zero;
|
||||
|
||||
/// <summary>
|
||||
/// The raycast hit for the projectile.
|
||||
/// </summary>
|
||||
RaycastHit m_Hit;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the projectile has hit a target.
|
||||
/// </summary>
|
||||
bool m_HasHitTarget = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the projectile belongs to the local player.
|
||||
/// </summary>
|
||||
bool m_LocalPlayerProjectile;
|
||||
|
||||
Action<Projectile> m_OnReturnToPool;
|
||||
|
||||
Rigidbody m_Rigidybody;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the projectile with the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="localPlayer">Indicates whether the projectile belongs to the local player.</param>
|
||||
/// <param name="playerColor">The color of the player.</param>
|
||||
public void Setup(bool localPlayer, Color playerColor, Action<Projectile> returnToPoolAction = null)
|
||||
{
|
||||
if (m_Rigidybody == null)
|
||||
{
|
||||
TryGetComponent(out m_Rigidybody);
|
||||
}
|
||||
|
||||
m_LocalPlayerProjectile = localPlayer;
|
||||
m_TrailRenderer.startColor = playerColor;
|
||||
m_TrailRenderer.endColor = playerColor;
|
||||
m_TrailRenderer.Clear();
|
||||
m_PrevPos = transform.position;
|
||||
if (returnToPoolAction != null)
|
||||
{
|
||||
m_OnReturnToPool = returnToPoolAction;
|
||||
StartCoroutine(ResetProjectileAfterTime());
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator ResetProjectileAfterTime()
|
||||
{
|
||||
yield return new WaitForSeconds(m_Lifetime);
|
||||
ResetProjectile();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!m_LocalPlayerProjectile || m_HasHitTarget) return;
|
||||
if (Physics.Linecast(m_PrevPos, transform.position, out m_Hit))
|
||||
{
|
||||
if (m_Hit.transform.CompareTag("Target"))
|
||||
{
|
||||
HitTarget(m_Hit.transform.GetComponentInParent<Target>());
|
||||
}
|
||||
|
||||
CheckForInteractableHit(m_Hit.transform);
|
||||
}
|
||||
|
||||
m_PrevPos = transform.position;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Target"))
|
||||
{
|
||||
HitTarget(other.GetComponentInParent<Target>());
|
||||
}
|
||||
}
|
||||
|
||||
void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
if (!m_LocalPlayerProjectile) return;
|
||||
CheckForInteractableHit(collision.transform);
|
||||
}
|
||||
|
||||
void CheckForInteractableHit(Transform t)
|
||||
{
|
||||
NetworkPhysicsInteractable networkPhysicsInteractable = t.GetComponentInParent<NetworkPhysicsInteractable>();
|
||||
if (networkPhysicsInteractable != null)
|
||||
{
|
||||
networkPhysicsInteractable.RequestOwnership();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the projectile hits a target.
|
||||
/// </summary>
|
||||
/// <param name="target">The target that was hit.</param>
|
||||
protected virtual void HitTarget(Target target)
|
||||
{
|
||||
target.TargetHitLocal();
|
||||
m_HasHitTarget = true;
|
||||
}
|
||||
|
||||
public void ResetProjectile()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
m_OnReturnToPool?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d181f0b4266f1f94cb661cf45595c347
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
using System.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XRMultiplayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a target object in the target practice gameplay.
|
||||
/// </summary>
|
||||
public class Target : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The target value.
|
||||
/// </summary>
|
||||
public int targetValue = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The animator for the target.
|
||||
/// </summary>
|
||||
[SerializeField] Animator m_Animator;
|
||||
|
||||
/// <summary>
|
||||
/// The collider for the target.
|
||||
/// </summary>
|
||||
[SerializeField] Collider m_TriggerCollider;
|
||||
|
||||
/// <summary>
|
||||
/// The particle system for the target.
|
||||
/// </summary>
|
||||
[SerializeField] ParticleSystem m_Particles;
|
||||
|
||||
/// <summary>
|
||||
/// The target manager for the target.
|
||||
/// </summary>
|
||||
TargetManager m_TargetManager;
|
||||
|
||||
/// <inheritdoc/>
|
||||
void Start()
|
||||
{
|
||||
m_TargetManager = GetComponentInParent<TargetManager>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables the target object.
|
||||
/// </summary>
|
||||
public void EnableTarget()
|
||||
{
|
||||
m_Animator.SetTrigger("Activate");
|
||||
m_TriggerCollider.enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the local target hit event.
|
||||
/// </summary>
|
||||
public void TargetHitLocal()
|
||||
{
|
||||
m_TargetManager.HitTargetServerRpc(NetworkManager.Singleton.LocalClientId, XRINetworkGameManager.LocalPlayerColor.Value);
|
||||
PlayHitEffects(XRINetworkGameManager.LocalPlayerColor.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the network target hit event.
|
||||
/// </summary>
|
||||
/// <param name="clientId">The ID of the client that hit the target.</param>
|
||||
/// <param name="playerColor">The color of the player who hit the target.</param>
|
||||
public void TargetHitNetwork(ulong clientId, Color playerColor)
|
||||
{
|
||||
if (NetworkManager.Singleton.LocalClientId != clientId)
|
||||
{
|
||||
PlayHitEffects(playerColor);
|
||||
}
|
||||
|
||||
if (m_TargetManager.IsServer)
|
||||
{
|
||||
StartCoroutine(TargetHitSequence());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays the hit effects for the target.
|
||||
/// </summary>
|
||||
/// <param name="playerColor"></param>
|
||||
void PlayHitEffects(Color playerColor)
|
||||
{
|
||||
m_Animator.SetTrigger("Hit");
|
||||
m_TriggerCollider.enabled = false;
|
||||
var main = m_Particles.main;
|
||||
main.startColor = playerColor;
|
||||
m_Particles.Play();
|
||||
StartCoroutine(HideAfterHit());
|
||||
}
|
||||
|
||||
IEnumerator HideAfterHit()
|
||||
{
|
||||
yield return new WaitForSeconds(3.0f);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the target hit sequence.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerator TargetHitSequence()
|
||||
{
|
||||
yield return new WaitForSeconds(2.25f);
|
||||
m_TargetManager.ServerIncreaseDifficulty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a272dbc7287bfa24bab3cc2e39c3a962
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,137 @@
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XRMultiplayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the targets in the target practice game.
|
||||
/// </summary>
|
||||
public class TargetManager : NetworkBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The targets in the game.
|
||||
/// </summary>
|
||||
public Target[] targets;
|
||||
|
||||
/// <summary>
|
||||
/// The difficulty level of the game.
|
||||
/// </summary>
|
||||
protected NetworkVariable<int> m_DifficultyLevel = new NetworkVariable<int>(-1, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the targets are activated.
|
||||
/// </summary>
|
||||
protected bool m_activated = false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void Start()
|
||||
{
|
||||
// Subscribe to difficulty level change events
|
||||
m_DifficultyLevel.OnValueChanged += OnDifficultyChanged;
|
||||
|
||||
// Deactivate all targets
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
targets[i].gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
base.OnNetworkSpawn();
|
||||
|
||||
// If the difficulty level is already set, manually trigger the difficulty change event
|
||||
if (m_DifficultyLevel.Value != -1)
|
||||
{
|
||||
OnDifficultyChanged(-1, m_DifficultyLevel.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the targets.
|
||||
/// </summary>
|
||||
public void ActivateTargets()
|
||||
{
|
||||
m_activated = true;
|
||||
|
||||
// Set the difficulty level to 0 on the server
|
||||
if (IsServer)
|
||||
{
|
||||
m_DifficultyLevel.Value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivates the targets.
|
||||
/// </summary>
|
||||
public void DeactivateTargets()
|
||||
{
|
||||
m_activated = false;
|
||||
|
||||
// Set the difficulty level to -1 on the server
|
||||
if (IsServer)
|
||||
{
|
||||
m_DifficultyLevel.Value = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the difficulty level changes.
|
||||
/// </summary>
|
||||
/// <param name="old">The old difficulty level.</param>
|
||||
/// <param name="current">The current difficulty level.</param>
|
||||
void OnDifficultyChanged(int old, int current)
|
||||
{
|
||||
// Activate the target corresponding to the current difficulty level and enable it
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
targets[i].gameObject.SetActive(current == i);
|
||||
if (current == i)
|
||||
{
|
||||
targets[i].EnableTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the difficulty level on the server.
|
||||
/// </summary>
|
||||
/// <param name="newDifficulty">The new difficulty level.</param>
|
||||
public void ServerSetDifficulty(int newDifficulty)
|
||||
{
|
||||
m_DifficultyLevel.Value = newDifficulty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increases the difficulty level on the server.
|
||||
/// </summary>
|
||||
public void ServerIncreaseDifficulty()
|
||||
{
|
||||
m_DifficultyLevel.Value = (m_DifficultyLevel.Value + 1) % targets.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server RPC method called when a target is hit.
|
||||
/// </summary>
|
||||
/// <param name="clientId">The client ID of the player who hit the target.</param>
|
||||
/// <param name="playerColor">The color of the player who hit the target.</param>
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void HitTargetServerRpc(ulong clientId, Color playerColor)
|
||||
{
|
||||
HitTargetClientRpc(clientId, playerColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Client RPC method called when a target is hit.
|
||||
/// </summary>
|
||||
/// <param name="clientId">The client ID of the player who hit the target.</param>
|
||||
/// <param name="playerColor">The color of the player who hit the target.</param>
|
||||
[ClientRpc]
|
||||
public void HitTargetClientRpc(ulong clientId, Color playerColor)
|
||||
{
|
||||
// Call the TargetHitNetwork method on the target corresponding to the current difficulty level
|
||||
targets[Mathf.Clamp(m_DifficultyLevel.Value, 0, targets.Length - 1)].TargetHitNetwork(clientId, playerColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d68a6a3d50c927749b49fe7bb42b655a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user