Initial commit

This commit is contained in:
Thorbjoern
2025-05-26 00:46:28 +02:00
commit e5bca03433
3896 changed files with 1434297 additions and 0 deletions
@@ -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: