Commit 33f6e76e by alsunj

add documenation and setup scene

parent 5dd86ee9
Showing with 1029 additions and 509 deletions
......@@ -54,3 +54,8 @@ MonoBehaviour:
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 6866275124911934084, guid: 97ac290fc57dc044a9e439c8e5a05a23, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
using Unity.Netcode;
using UnityEngine;
/// <summary>
/// Represents an animated enemy in the game, inheriting from the base Enemy class.
/// This class handles initialization of enemy-specific components such as the EnemyManager
/// and EnemyAnimator, and provides functionality for enemy animations and events.
/// </summary>
public class AnimatedEnemy : Enemy
{
/// <summary>
/// Reference to the EnemyAnimator component, which handles animation-related events.
/// </summary>
protected EnemyAnimator _enemyAnimator;
/// <summary>
/// Reference to the EnemyManager component, which manages enemy-specific logic and events.
/// </summary>
protected EnemyManager _enemyManager;
/// <summary>
/// Initializes the enemy with the specified detection range and target layer mask.
/// This method also initializes the EnemyManager and EnemyAnimator components.
/// </summary>
/// <param name="detectionRange">The range within which the enemy can detect targets.</param>
/// <param name="targetLayerMask">The layer mask used to identify valid targets.</param>
protected override void InitializeEnemy(int detectionRange, LayerMask targetLayerMask)
{
base.InitializeEnemy(detectionRange, targetLayerMask);
// Initialize the EnemyManager component
_enemyManager = GetComponent<EnemyManager>();
if (_enemyManager != null)
{
......@@ -19,35 +39,14 @@ public class AnimatedEnemy : Enemy
Debug.LogError("EnemyManager is not set in the inspector");
}
// Initialize the EnemyAnimator component and bind its events
_enemyAnimator = GetComponentInChildren<EnemyAnimator>();
_enemyAnimator.InitializeEvents(_enemyManager.enemyEvents);
// if (_enemyAnimator != null)
// {
// _enemyAnimator.InitializeEvents(_enemyManager.enemyEvents);
// _enemyAnimator.receiveTargetShotEventFromAnimator += TargetShotEventServerRpc;
// _enemyAnimator.receiveTargetAimedEventFromAnimator += ShootTargetServerRpc;
// _enemyAnimator.receiveTargetReloadEventFromAnimator += ReloadCrossbowServerRpc;
// }
}
// not possible to raise the functions to inheritor
// [ServerRpc]
// protected virtual void ReloadCrossbowServerRpc()
// {
// }
//
// [ServerRpc]
// protected virtual void ShootTargetServerRpc()
// {
// _enemyManager.enemyEvents.EnemyAttack();
// }
//
// [ServerRpc]
// protected virtual void TargetShotEventServerRpc()
// {
// _enemyManager.enemyEvents.EnemyReload();
// }
/// <summary>
/// Handles aiming at the target by triggering the appropriate enemy event.
/// </summary>
protected virtual void AimAtTarget()
{
_enemyManager.enemyEvents.EnemyAim();
......
using Unity.Netcode;
using UnityEngine;
public class DamageCollision : NetworkBehaviour
/// <summary>
/// Manages collision-based damage interactions in a networked environment.
/// This class handles damage application, object despawning, and client-side updates
/// for projectiles and enemies upon collision with targets or terrain.
/// </summary>
public class DamageCollisionManager : NetworkBehaviour
{
/// <summary>
/// Settings for damage collision, including target and terrain layers and damage amount.
/// </summary>
[SerializeField] private DamageCollisionSettings _damageCollisionSettings;
private int _targetLayer;
private int _terrainLayer;
private int _damage;
private int _targetLayer; // Layer for target objects (e.g., players).
private int _terrainLayer; // Layer for terrain objects.
private int _damage; // Amount of damage to apply to targets.
/// <summary>
/// Called when the object is spawned on the network.
/// Initializes layer and damage values from the provided settings.
/// </summary>
public override void OnNetworkSpawn()
{
_targetLayer = GetLayerFromLayerMask(_damageCollisionSettings.targetLayer);
......@@ -15,21 +28,27 @@ public class DamageCollision : NetworkBehaviour
_damage = _damageCollisionSettings.damageAmount;
}
/// <summary>
/// Handles collision events and applies appropriate logic based on the collided object's layer.
/// </summary>
/// <param name="other">The collision data of the object this collided with.</param>
private void OnCollisionEnter(Collision other)
{
if (IsServer)
if (IsServer) // Ensure logic is executed only on the server.
{
if (other.gameObject.layer == _targetLayer)
{
// Apply damage to the target if it has a PlayerHealth component.
other.gameObject.GetComponent<PlayerHealth>().decreaseHealth(_damage);
// Handle enemy despawning and removal from targeting list.
if (gameObject.TryGetComponent(out Slime enemyComponent))
{
TargetingManager.Instance.RemoveEnemyFromTargetingList(enemyComponent);
gameObject.GetComponent<NetworkObject>().Despawn();
Destroy(this);
}
// Handle arrow-specific logic for disabling the arrow on clients.
if (gameObject.TryGetComponent(out Arrow arrowComponent))
{
NetworkObjectReference arrowNetworkObjectReference =
......@@ -40,6 +59,7 @@ public class DamageCollision : NetworkBehaviour
if (other.gameObject.layer == _terrainLayer)
{
// Handle arrow-specific logic for disabling the arrow on clients when hitting terrain.
if (gameObject.TryGetComponent(out Arrow arrowComponent))
{
NetworkObjectReference arrowNetworkObjectReference =
......@@ -50,6 +70,10 @@ public class DamageCollision : NetworkBehaviour
}
}
/// <summary>
/// Disables the arrow object on all clients.
/// </summary>
/// <param name="arrowReference">A reference to the arrow's NetworkObject.</param>
[ClientRpc]
private void DisableArrowClientRpc(NetworkObjectReference arrowReference)
{
......@@ -59,6 +83,11 @@ public class DamageCollision : NetworkBehaviour
}
}
/// <summary>
/// Converts a LayerMask to its corresponding layer index.
/// </summary>
/// <param name="layerMask">The LayerMask to convert.</param>
/// <returns>The index of the layer, or -1 if the LayerMask is invalid.</returns>
public static int GetLayerFromLayerMask(LayerMask layerMask)
{
int value = layerMask.value;
......
......@@ -2,12 +2,33 @@ using System;
using Unity.Netcode;
using UnityEngine;
/// <summary>
/// Represents a base class for enemies in the game.
/// Provides properties and methods for enemy initialization and behavior.
/// </summary>
public class Enemy : NetworkBehaviour
{
/// <summary>
/// Gets or sets the detection radius of the enemy.
/// This defines the range within which the enemy can detect targets.
/// </summary>
public int DetectionRadius { get; set; }
/// <summary>
/// Gets or sets the current target of the enemy.
/// </summary>
public Transform Target { get; set; }
/// <summary>
/// Gets or sets the layer mask used to identify valid targets for the enemy.
/// </summary>
public LayerMask TargetLayerMask { get; set; }
/// <summary>
/// Initializes the enemy with the specified detection range and target layer mask.
/// </summary>
/// <param name="detectionRange">The range within which the enemy can detect targets.</param>
/// <param name="targetLayerMask">The layer mask used to identify valid targets.</param>
protected virtual void InitializeEnemy(int detectionRange, LayerMask targetLayerMask)
{
DetectionRadius = detectionRange;
......@@ -15,6 +36,9 @@ public class Enemy : NetworkBehaviour
Target = null;
}
// /// <summary>
// /// Removes the enemy from the targeting list when it is destroyed.
// /// </summary>
// public override void OnDestroy()
// {
// TargetingManager.Instance.RemoveEnemyFromTargetingList(this);
......
......@@ -3,20 +3,37 @@ using System.Collections;
using Unity.VisualScripting;
using UnityEngine;
/// <summary>
/// Handles enemy animation events and triggers animations for aiming, reloading, and attacking.
/// This class also integrates with the EnemyEvents system to respond to enemy-specific actions.
/// </summary>
public class EnemyAnimator : MonoBehaviour
{
private const string IS_AIMING = "Aim";
private const string IS_RELOADING = "Reload";
private const string IS_ATTACKING = "Attack";
private const string IS_AIMING = "Aim"; // Animation trigger for aiming.
private const string IS_RELOADING = "Reload"; // Animation trigger for reloading.
private const string IS_ATTACKING = "Attack"; // Animation trigger for attacking.
private EnemyEvents _enemyEvents;
private Animator _animator;
private EnemyEvents _enemyEvents; // Reference to the EnemyEvents instance.
private Animator _animator; // Reference to the Animator component.
/// <summary>
/// Event triggered when the animator signals that the target has been shot.
/// </summary>
public event Action receiveTargetShotEventFromAnimator;
/// <summary>
/// Event triggered when the animator signals that the target has been aimed at.
/// </summary>
public event Action receiveTargetAimedEventFromAnimator;
public event Action receiveTargetReloadEventFromAnimator;
/// <summary>
/// Event triggered when the animator signals that the target has been reloaded.
/// </summary>
public event Action receiveTargetReloadEventFromAnimator;
/// <summary>
/// Unsubscribes from EnemyEvents when the object is disabled.
/// </summary>
private void OnDisable()
{
if (_enemyEvents != null)
......@@ -27,6 +44,11 @@ public class EnemyAnimator : MonoBehaviour
}
}
/// <summary>
/// Initializes the EnemyAnimator with the provided EnemyEvents instance.
/// Binds animation triggers to the corresponding enemy events.
/// </summary>
/// <param name="enemyEvents">The EnemyEvents instance to bind to.</param>
public void InitializeEvents(EnemyEvents enemyEvents)
{
_animator = GetComponentInChildren<Animator>();
......@@ -44,31 +66,49 @@ public class EnemyAnimator : MonoBehaviour
}
}
/// <summary>
/// Invokes the event when the animator signals that the target has been aimed at.
/// </summary>
private void ReceiveTargetAimedEventFromAnimator()
{
receiveTargetAimedEventFromAnimator?.Invoke();
}
/// <summary>
/// Invokes the event when the animator signals that the target has been reloaded.
/// </summary>
private void ReceiveTargetReloadEventFromAnimator()
{
receiveTargetReloadEventFromAnimator?.Invoke();
}
/// <summary>
/// Invokes the event when the animator signals that the target has been shot.
/// </summary>
private void ReceiveTargetShotEventFromAnimator()
{
receiveTargetShotEventFromAnimator?.Invoke();
}
/// <summary>
/// Triggers the reload animation for the enemy.
/// </summary>
private void SetEnemyReload()
{
_animator.SetTrigger(IS_RELOADING);
}
/// <summary>
/// Triggers the aim animation for the enemy.
/// </summary>
private void SetEnemyAim()
{
_animator.SetTrigger(IS_AIMING);
}
/// <summary>
/// Triggers the attack animation for the enemy.
/// </summary>
private void SetEnemyAttack()
{
_animator.SetTrigger(IS_ATTACKING);
......
......@@ -3,19 +3,39 @@ using DG.Tweening;
using Unity.Netcode;
using UnityEngine;
/// <summary>
/// Represents a Rogue enemy, inheriting from AnimatedEnemy.
/// This class handles the initialization and behavior of the Rogue, including aiming, shooting, and reloading.
/// </summary>
public class Rogue : AnimatedEnemy
{
/// <summary>
/// Settings for the enemy, including detection range, target layer, and shooting delay.
/// </summary>
[SerializeField] private EnemySettings enemySettings;
/// <summary>
/// Prefab for the arrow used by the Rogue.
/// </summary>
[SerializeField] private GameObject arrow;
/// <summary>
/// Reference to the weapon GameObject used by the Rogue.
/// </summary>
[SerializeField] private GameObject weapon;
private Arrow _arrowComponent;
private float _shootingCooldown;
private bool _isAiming;
private Vector3 _lookingDirection;
private NetworkObject _instantiatedArrow;
private Transform _arrowSpawnPoint;
private Rigidbody _arrowRigidbody;
private Arrow _arrowComponent; // Reference to the Arrow component of the instantiated arrow.
private float _shootingCooldown; // Cooldown timer for shooting.
private bool _isAiming; // Indicates whether the Rogue is currently aiming.
private Vector3 _lookingDirection; // Direction the Rogue is looking towards.
private NetworkObject _instantiatedArrow; // Networked instance of the arrow.
private Transform _arrowSpawnPoint; // Spawn point for the arrow.
private Rigidbody _arrowRigidbody; // Rigidbody component of the arrow.
/// <summary>
/// Called when the Rogue is spawned on the network.
/// Initializes the enemy with the specified settings.
/// </summary>
public override void OnNetworkSpawn()
{
if (IsServer)
......@@ -24,9 +44,16 @@ public class Rogue : AnimatedEnemy
}
}
/// <summary>
/// Initializes the Rogue with the specified detection range and target layer mask.
/// Sets up event listeners and validates required components.
/// </summary>
/// <param name="detectionRange">The range within which the Rogue can detect targets.</param>
/// <param name="targetLayerMask">The layer mask used to identify valid targets.</param>
protected override void InitializeEnemy(int detectionRange, LayerMask targetLayerMask)
{
base.InitializeEnemy(detectionRange, targetLayerMask);
if (_enemyAnimator != null)
{
_enemyAnimator.receiveTargetShotEventFromAnimator += TargetShotEvent;
......@@ -50,7 +77,6 @@ public class Rogue : AnimatedEnemy
_arrowSpawnPoint = weapon.transform.Find("Skeleton_Crossbow/ArrowSpawnPoint");
if (_arrowSpawnPoint == null)
{
throw new Exception("ArrowSpawnPoint is not found as a child of Weapon");
}
......@@ -60,11 +86,12 @@ public class Rogue : AnimatedEnemy
throw new Exception("Arrow is not set in the inspector");
}
InstantiateArrow();
}
/// <summary>
/// Instantiates the arrow at the spawn point and sets up its components.
/// </summary>
public void InstantiateArrow()
{
_instantiatedArrow = Instantiate(arrow, _arrowSpawnPoint.position, _arrowSpawnPoint.rotation)
......@@ -75,9 +102,13 @@ public class Rogue : AnimatedEnemy
_arrowComponent.SetTargetTransform(_arrowSpawnPoint.transform);
}
/// <summary>
/// Updates the Rogue's behavior, including cooldown management and target rotation.
/// </summary>
private void Update()
{
if (!IsServer) return;
if (_shootingCooldown > 0)
{
_shootingCooldown -= Time.deltaTime;
......@@ -90,6 +121,9 @@ public class Rogue : AnimatedEnemy
}
}
/// <summary>
/// Handles aiming at the target. If the arrow is inactive, triggers a reload.
/// </summary>
protected override void AimAtTarget()
{
if (!_instantiatedArrow.gameObject.activeSelf)
......@@ -101,6 +135,9 @@ public class Rogue : AnimatedEnemy
base.AimAtTarget();
}
/// <summary>
/// Rotates the Rogue to face the target and triggers the aim action.
/// </summary>
private void RotateTowardsTarget()
{
_lookingDirection = (Target.position - transform.position).normalized;
......@@ -110,12 +147,18 @@ public class Rogue : AnimatedEnemy
AimAtTarget();
}
/// <summary>
/// Handles shooting at the target and sets the shooting cooldown.
/// </summary>
private void ShootTarget()
{
_enemyManager.enemyEvents.EnemyAttack();
_shootingCooldown = enemySettings.shootingDelay;
}
/// <summary>
/// Handles the event when the target is shot. Reloads the crossbow and applies velocity to the arrow.
/// </summary>
private void TargetShotEvent()
{
_enemyManager.enemyEvents.EnemyReload();
......@@ -123,6 +166,9 @@ public class Rogue : AnimatedEnemy
_arrowRigidbody.linearVelocity = _lookingDirection * enemySettings.shootingRange;
}
/// <summary>
/// Reloads the crossbow by resetting the arrow's position and enabling it on clients.
/// </summary>
private void ReloadCrossbow()
{
_arrowRigidbody.linearVelocity = Vector3.zero;
......@@ -131,7 +177,10 @@ public class Rogue : AnimatedEnemy
EnableArrowClientRpc(arrowReference);
}
/// <summary>
/// Enables the arrow on all clients.
/// </summary>
/// <param name="arrowReference">A reference to the arrow's NetworkObject.</param>
[ClientRpc]
private void EnableArrowClientRpc(NetworkObjectReference arrowReference)
{
......
using UnityEngine;
/// <summary>
/// Represents a Slime enemy, inheriting from the base Enemy class.
/// This class handles the initialization and movement behavior of the Slime enemy.
/// </summary>
public class Slime : Enemy
{
/// <summary>
/// Settings for the Slime enemy, including detection range, target layer, and movement speed.
/// </summary>
[SerializeField] private EnemySettings enemySettings;
/// <summary>
/// Reference to the Rigidbody component used for controlling the Slime's movement.
/// </summary>
private Rigidbody _rigidbody;
private int _targetLayer;
/// <summary>
/// Layer mask for identifying valid target objects.
/// </summary>
private int _targetLayer;
/// <summary>
/// Called when the Slime is spawned on the network.
/// Initializes the enemy with the specified settings.
/// </summary>
public override void OnNetworkSpawn()
{
if (IsServer)
......@@ -15,12 +33,22 @@ public class Slime : Enemy
}
}
/// <summary>
/// Initializes the Slime with the specified detection range and target layer mask.
/// Sets up the Rigidbody component for movement.
/// </summary>
/// <param name="detectionRange">The range within which the Slime can detect targets.</param>
/// <param name="targetLayerMask">The layer mask used to identify valid targets.</param>
protected override void InitializeEnemy(int detectionRange, LayerMask targetLayerMask)
{
base.InitializeEnemy(detectionRange, targetLayerMask);
_rigidbody = GetComponent<Rigidbody>();
}
/// <summary>
/// Updates the Slime's movement behavior.
/// Moves the Slime towards its target if a target is detected.
/// </summary>
private void Update()
{
if (Target)
......
using System.Collections;
using Unity.Netcode;
using UnityEngine;
public class EnemySpawnerManager : NetworkBehaviour
{
[SerializeField] private GameObject _rogueEnemyPrefab;
[SerializeField] private GameObject _slimeEnemyPrefab;
private Transform[] _enemySpawnLocations;
#region EnemyConfig
private int _RougeEnemySpawnAmount;
private int _SlimeEnemySpawnAmount;
private float _RogueEnemySpawnCooldown;
private float _SlimeEnemySpawnCooldown;
#endregion
#region runtimeEnemyProperties
private float _RogueEnemySpawnTimer;
private float _SlimeEnemySpawnTimer;
private int _spawnedRogueEnemyCount;
private int _spawnedSlimeEnemyCount;
#endregion
void Start()
{
if (IsServer)
{
OnServerStarted();
}
}
private void OnServerStarted()
{
// ApplyExistingEnemyArrows();
FindEnemySpawnPositions();
FindEnemyConfig();
StartEnemySpawnTimers();
}
private void StartEnemySpawnTimers()
{
StartCoroutine(RogueSpawnTimerCoroutine());
StartCoroutine(SlimeSpawnTimerCoroutine());
}
private IEnumerator RogueSpawnTimerCoroutine()
{
while (_spawnedRogueEnemyCount < _RougeEnemySpawnAmount)
{
if (_RogueEnemySpawnTimer <= 0f)
{
var random = new Unity.Mathematics.Random((uint)System.DateTime.Now.Ticks);
Vector3 spawnPosition = GetSpawnPosition(_spawnedRogueEnemyCount);
spawnPosition += new Vector3(random.NextFloat(-5f, 5f), 0, random.NextFloat(-5f, 5f));
SpawnRogueEnemy(spawnPosition);
_spawnedRogueEnemyCount++;
_RogueEnemySpawnTimer = _RogueEnemySpawnCooldown;
}
_RogueEnemySpawnTimer -= Time.fixedDeltaTime; // Use Time.fixedDeltaTime for physics updates
yield return new WaitForFixedUpdate(); // Wait for the next physics update
}
}
private IEnumerator SlimeSpawnTimerCoroutine()
{
while (_spawnedSlimeEnemyCount < _SlimeEnemySpawnAmount)
{
if (_SlimeEnemySpawnTimer <= 0f)
{
var random = new Unity.Mathematics.Random((uint)System.DateTime.Now.Ticks);
Vector3 spawnPosition = GetSpawnPosition(_spawnedSlimeEnemyCount);
spawnPosition += new Vector3(random.NextFloat(-5f, 5f), 0, random.NextFloat(-5f, 5f));
SpawnSlimeEnemy(spawnPosition);
_spawnedSlimeEnemyCount++;
_SlimeEnemySpawnTimer = _SlimeEnemySpawnCooldown;
}
_SlimeEnemySpawnTimer -= Time.fixedDeltaTime; // Use Time.fixedDeltaTime for physics updates
yield return new WaitForFixedUpdate(); // Wait for the next physics update
}
}
private void SpawnRogueEnemy(Vector3 spawnPosition)
{
if (_rogueEnemyPrefab != null)
{
GameObject spawnedEnemy =
Instantiate(_rogueEnemyPrefab, spawnPosition, Quaternion.identity, gameObject.transform);
spawnedEnemy.GetComponent<NetworkObject>().Spawn();
TargetingManager.Instance.AddEnemyToTargetingList(spawnedEnemy.GetComponent<Enemy>());
}
}
private void SpawnSlimeEnemy(Vector3 spawnPosition)
{
if (_slimeEnemyPrefab != null)
{
GameObject spawnedEnemy =
Instantiate(_slimeEnemyPrefab, spawnPosition, Quaternion.identity, gameObject.transform);
spawnedEnemy.GetComponent<NetworkObject>().Spawn();
TargetingManager.Instance.AddEnemyToTargetingList(spawnedEnemy.GetComponent<Enemy>());
}
}
private Vector3 GetSpawnPosition(int spawnedCount)
{
int index = spawnedCount % _enemySpawnLocations.Length;
return _enemySpawnLocations[index].position;
}
private void FindEnemyConfig()
{
_RougeEnemySpawnAmount = GameDataConfig.Instance.RogueEnemyAmount;
_SlimeEnemySpawnAmount = GameDataConfig.Instance.SlimeEnemyAmount;
_RogueEnemySpawnCooldown = GameDataConfig.Instance.RogueEnemySpawnTimer;
_SlimeEnemySpawnCooldown = GameDataConfig.Instance.SlimeEnemySpawnTimer;
_RogueEnemySpawnTimer = _RogueEnemySpawnCooldown;
_SlimeEnemySpawnTimer = _SlimeEnemySpawnCooldown;
}
private void FindEnemySpawnPositions()
{
GameObject spawnLocationParent = GameObject.Find("EnemySpawnLocations");
if (spawnLocationParent == null)
{
Debug.LogError("Could not find GameObject named 'EnemySpawnLocations'!");
return;
}
_enemySpawnLocations = new Transform[spawnLocationParent.transform.childCount];
for (int i = 0; i < spawnLocationParent.transform.childCount; i++)
{
_enemySpawnLocations[i] = spawnLocationParent.transform.GetChild(i);
}
Vector3[] spawnPositions = new Vector3[_enemySpawnLocations.Length];
for (int i = 0; i < _enemySpawnLocations.Length; i++)
{
spawnPositions[i] = _enemySpawnLocations[i].position;
}
}
}
\ No newline at end of file
using UnityEngine;
/// <summary>
/// Manages enemy-related functionality in the game, including initializing enemy events.
/// </summary>
public class EnemyManager : MonoBehaviour
{
/// <summary>
/// Handles events related to enemy actions such as attacking, aiming, and reloading.
/// </summary>
public EnemyEvents enemyEvents;
/// <summary>
/// Initializes the EnemyManager by creating a new instance of EnemyEvents.
/// </summary>
public void Initialize()
{
enemyEvents = new EnemyEvents();
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: cb139732cb33148458fab05d76c66791
\ No newline at end of file
guid: 6b51ffc7252b86b43a0b4806229fd39d
\ No newline at end of file
using System.Collections;
using Unity.Netcode;
using UnityEngine;
public class EnemyManager : MonoBehaviour
/// <summary>
/// Manages the spawning of enemies in the game, including Rogue and Slime enemies.
/// Handles spawn timers, spawn locations, and enemy instantiation.
/// </summary>
public class EnemySpawnerManager : NetworkBehaviour
{
public EnemyEvents enemyEvents;
/// <summary>
/// Singleton instance of the EnemySpawnerManager.
/// </summary>
public static EnemySpawnerManager Instance { get; private set; }
public void Initialize()
[SerializeField] private GameObject _rogueEnemyPrefab; // Prefab for Rogue enemies.
[SerializeField] private GameObject _slimeEnemyPrefab; // Prefab for Slime enemies.
private Transform[] _enemySpawnLocations; // Array of spawn locations for enemies.
#region EnemyConfig
private int _RougeEnemySpawnAmount; // Total number of Rogue enemies to spawn.
private int _SlimeEnemySpawnAmount; // Total number of Slime enemies to spawn.
private float _RogueEnemySpawnCooldown; // Cooldown time between Rogue enemy spawns.
private float _SlimeEnemySpawnCooldown; // Cooldown time between Slime enemy spawns.
#endregion
#region runtimeEnemyProperties
private float _RogueEnemySpawnTimer; // Timer for Rogue enemy spawning.
private float _SlimeEnemySpawnTimer; // Timer for Slime enemy spawning.
private int _spawnedRogueEnemyCount; // Count of spawned Rogue enemies.
private int _spawnedSlimeEnemyCount; // Count of spawned Slime enemies.
#endregion
/// <summary>
/// Ensures only one instance of EnemySpawnerManager exists and persists across scenes.
/// </summary>
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
/// <summary>
/// Initializes the server-specific logic when the game starts.
/// </summary>
private void Start()
{
if (IsServer)
{
OnServerStarted();
}
}
/// <summary>
/// Sets up enemy spawn positions and configurations when the server starts.
/// </summary>
private void OnServerStarted()
{
FindEnemySpawnPositions();
FindEnemyConfig();
}
/// <summary>
/// Starts the spawn timers for Rogue and Slime enemies.
/// </summary>
public void StartEnemySpawnTimers()
{
StartCoroutine(RogueSpawnTimerCoroutine());
StartCoroutine(SlimeSpawnTimerCoroutine());
}
/// <summary>
/// Coroutine to handle Rogue enemy spawning based on the spawn timer.
/// </summary>
private IEnumerator RogueSpawnTimerCoroutine()
{
while (_spawnedRogueEnemyCount < _RougeEnemySpawnAmount)
{
enemyEvents = new EnemyEvents();
if (_RogueEnemySpawnTimer <= 0f)
{
var random = new Unity.Mathematics.Random((uint)System.DateTime.Now.Ticks);
Vector3 spawnPosition = GetSpawnPosition(_spawnedRogueEnemyCount);
spawnPosition += new Vector3(random.NextFloat(-5f, 5f), 0, random.NextFloat(-5f, 5f));
SpawnRogueEnemy(spawnPosition);
_spawnedRogueEnemyCount++;
_RogueEnemySpawnTimer = _RogueEnemySpawnCooldown;
}
_RogueEnemySpawnTimer -= Time.fixedDeltaTime;
yield return new WaitForFixedUpdate();
}
}
/// <summary>
/// Coroutine to handle Slime enemy spawning based on the spawn timer.
/// </summary>
private IEnumerator SlimeSpawnTimerCoroutine()
{
while (_spawnedSlimeEnemyCount < _SlimeEnemySpawnAmount)
{
if (_SlimeEnemySpawnTimer <= 0f)
{
var random = new Unity.Mathematics.Random((uint)System.DateTime.Now.Ticks);
Vector3 spawnPosition = GetSpawnPosition(_spawnedSlimeEnemyCount);
spawnPosition += new Vector3(random.NextFloat(-5f, 5f), 0, random.NextFloat(-5f, 5f));
SpawnSlimeEnemy(spawnPosition);
_spawnedSlimeEnemyCount++;
_SlimeEnemySpawnTimer = _SlimeEnemySpawnCooldown;
}
_SlimeEnemySpawnTimer -= Time.fixedDeltaTime;
yield return new WaitForFixedUpdate();
}
}
/// <summary>
/// Spawns a Rogue enemy at the specified position.
/// </summary>
/// <param name="spawnPosition">The position to spawn the Rogue enemy.</param>
private void SpawnRogueEnemy(Vector3 spawnPosition)
{
if (_rogueEnemyPrefab != null)
{
GameObject spawnedEnemy =
Instantiate(_rogueEnemyPrefab, spawnPosition, Quaternion.identity, gameObject.transform);
spawnedEnemy.GetComponent<NetworkObject>().Spawn();
TargetingManager.Instance.AddEnemyToTargetingList(spawnedEnemy.GetComponent<Enemy>());
}
}
/// <summary>
/// Spawns a Slime enemy at the specified position.
/// </summary>
/// <param name="spawnPosition">The position to spawn the Slime enemy.</param>
private void SpawnSlimeEnemy(Vector3 spawnPosition)
{
if (_slimeEnemyPrefab != null)
{
GameObject spawnedEnemy =
Instantiate(_slimeEnemyPrefab, spawnPosition, Quaternion.identity, gameObject.transform);
spawnedEnemy.GetComponent<NetworkObject>().Spawn();
TargetingManager.Instance.AddEnemyToTargetingList(spawnedEnemy.GetComponent<Enemy>());
}
}
/// <summary>
/// Gets the spawn position for an enemy based on the spawn count.
/// </summary>
/// <param name="spawnedCount">The number of enemies already spawned.</param>
/// <returns>The spawn position for the next enemy.</returns>
private Vector3 GetSpawnPosition(int spawnedCount)
{
int index = spawnedCount % _enemySpawnLocations.Length;
return _enemySpawnLocations[index].position;
}
/// <summary>
/// Retrieves enemy configuration data from the game configuration.
/// </summary>
private void FindEnemyConfig()
{
_RougeEnemySpawnAmount = GameDataConfig.Instance.RogueEnemyAmount;
_SlimeEnemySpawnAmount = GameDataConfig.Instance.SlimeEnemyAmount;
_RogueEnemySpawnCooldown = GameDataConfig.Instance.RogueEnemySpawnTimer;
_SlimeEnemySpawnCooldown = GameDataConfig.Instance.SlimeEnemySpawnTimer;
_RogueEnemySpawnTimer = _RogueEnemySpawnCooldown;
_SlimeEnemySpawnTimer = _SlimeEnemySpawnCooldown;
}
/// <summary>
/// Finds and stores enemy spawn locations from the scene.
/// </summary>
private void FindEnemySpawnPositions()
{
GameObject spawnLocationParent = GameObject.Find("EnemySpawnLocations");
if (spawnLocationParent == null)
{
Debug.LogError("Could not find GameObject named 'EnemySpawnLocations'!");
return;
}
_enemySpawnLocations = new Transform[spawnLocationParent.transform.childCount];
for (int i = 0; i < spawnLocationParent.transform.childCount; i++)
{
_enemySpawnLocations[i] = spawnLocationParent.transform.GetChild(i);
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 6b51ffc7252b86b43a0b4806229fd39d
\ No newline at end of file
guid: cb139732cb33148458fab05d76c66791
\ No newline at end of file
using System;
/// <summary>
/// Manages events related to enemy actions such as attacking, aiming, and reloading.
/// Provides methods to trigger these events and allows other components to subscribe to them.
/// </summary>
public class EnemyEvents
{
/// <summary>
/// Event triggered when an enemy performs an attack.
/// </summary>
public event Action onEnemyAttack;
/// <summary>
/// Event triggered when an enemy starts aiming.
/// </summary>
public event Action onEnemyAim;
/// <summary>
/// Event triggered when an enemy reloads its weapon.
/// </summary>
public event Action onEnemyReload;
/// <summary>
/// Triggers the onEnemyAttack event to notify subscribers that an enemy has attacked.
/// </summary>
public void EnemyAttack()
{
if (onEnemyAttack != null)
......@@ -14,6 +32,9 @@ public class EnemyEvents
}
}
/// <summary>
/// Triggers the onEnemyAim event to notify subscribers that an enemy has started aiming.
/// </summary>
public void EnemyAim()
{
if (onEnemyAim != null)
......@@ -22,6 +43,9 @@ public class EnemyEvents
}
}
/// <summary>
/// Triggers the onEnemyReload event to notify subscribers that an enemy has reloaded its weapon.
/// </summary>
public void EnemyReload()
{
if (onEnemyReload != null)
......
using System;
/// <summary>
/// Manages events related to player actions such as walking, running, defending, interacting, and attacking.
/// Provides methods to trigger these events and allows other components to subscribe to them.
/// </summary>
public class PlayerEvents
{
/// <summary>
/// Event triggered when the player starts or stops walking.
/// The boolean parameter indicates whether the player is walking (true) or not (false).
/// </summary>
public event Action<bool> onPlayerWalk;
/// <summary>
/// Event triggered when the player starts or stops running.
/// The boolean parameter indicates whether the player is running (true) or not (false).
/// </summary>
public event Action<bool> onPlayerRun;
/// <summary>
/// Event triggered when the player starts or stops defending.
/// The boolean parameter indicates whether the player is defending (true) or not (false).
/// </summary>
public event Action<bool> onPlayerDefence;
/// <summary>
/// Event triggered when the player interacts with an object.
/// </summary>
public event Action onPlayerInteract;
public event Action onPlayerAttack;
/// <summary>
/// Event triggered when the player performs an attack.
/// </summary>
public event Action onPlayerAttack;
/// <summary>
/// Triggers the onPlayerDefence event to notify subscribers that the player has started or stopped defending.
/// </summary>
/// <param name="state">Indicates whether the player is defending (true) or not (false).</param>
public void PlayerDefence(bool state)
{
if (onPlayerDefence != null)
......@@ -17,6 +46,10 @@ public class PlayerEvents
}
}
/// <summary>
/// Triggers the onPlayerWalk event to notify subscribers that the player has started or stopped walking.
/// </summary>
/// <param name="state">Indicates whether the player is walking (true) or not (false).</param>
public void PlayerWalk(bool state)
{
if (onPlayerWalk != null)
......@@ -25,6 +58,10 @@ public class PlayerEvents
}
}
/// <summary>
/// Triggers the onPlayerRun event to notify subscribers that the player has started or stopped running.
/// </summary>
/// <param name="state">Indicates whether the player is running (true) or not (false).</param>
public void PlayerRun(bool state)
{
if (onPlayerRun != null)
......@@ -33,6 +70,9 @@ public class PlayerEvents
}
}
/// <summary>
/// Triggers the onPlayerInteract event to notify subscribers that the player has interacted with an object.
/// </summary>
public void PlayerInteract()
{
if (onPlayerInteract != null)
......@@ -41,6 +81,9 @@ public class PlayerEvents
}
}
/// <summary>
/// Triggers the onPlayerAttack event to notify subscribers that the player has performed an attack.
/// </summary>
public void PlayerAttack()
{
if (onPlayerAttack != null)
......
......@@ -5,119 +5,119 @@ using UnityEngine;
public class GameManager : NetworkBehaviour
{
[SerializeField] private GameObject keyPrefab;
[SerializeField] private bool startGame;
private TextMeshProUGUI _timerText;
private float _initialTimer = 10f;
private float _startGameTimer = 10f;
private bool _initialTimerActive = true;
private bool _startGameTimerActive;
private void Start()
{
_timerText = GameObject.Find("Start_Game").GetComponent<TextMeshProUGUI>();
if (_timerText == null)
{
Debug.LogError("TextMeshPro component not found on Start Game GameObject!");
return;
}
if (IsServer)
{
// _initialTimerActive = startGame;
}
_initialTimerActive = startGame;
}
private void Update()
{
if (!IsServer) return;
if (_initialTimerActive)
{
_initialTimer -= Time.deltaTime;
if (_initialTimer <= 0)
{
_initialTimerActive = false;
_startGameTimerActive = true;
EnableTimerTextClientRpc(true);
}
}
if (_startGameTimerActive)
{
_startGameTimer -= Time.deltaTime;
if (_startGameTimer > 0)
{
UpdateTimerClientRpc(_startGameTimer);
}
else
{
_startGameTimerActive = false;
UpdateTimerClientRpc(0);
EnableTimerTextClientRpc(false);
TimersEndedServerRpc();
}
}
}
[ClientRpc]
private void UpdateTimerClientRpc(float timeRemaining)
{
if (_timerText != null)
{
_timerText.text = $"Starting Game in {Mathf.Ceil(timeRemaining)}";
}
}
[ClientRpc]
private void EnableTimerTextClientRpc(bool state)
{
if (_timerText != null)
{
_timerText.enabled = state;
}
}
[ServerRpc]
private void TimersEndedServerRpc()
{
for (int i = 0; i < 2; i++)
{
Vector3 spawnPosition = new Vector3(10 + UnityEngine.Random.Range(-5f, 5f), 0,
10 + Random.Range(-5f, 5f));
GameObject obj = Instantiate(keyPrefab, spawnPosition, Quaternion.identity);
obj.GetComponent<NetworkObject>().Spawn();
}
}
[ServerRpc(RequireOwnership = false)]
public void RequestTimerStateServerRpc(ServerRpcParams rpcParams = default)
{
if (_initialTimerActive)
{
RespondTimerStateClientRpc(_initialTimer, true, rpcParams.Receive.SenderClientId);
}
else if (_startGameTimerActive)
{
RespondTimerStateClientRpc(_startGameTimer, true, rpcParams.Receive.SenderClientId);
}
else
{
RespondTimerStateClientRpc(0, false, rpcParams.Receive.SenderClientId);
}
}
[ClientRpc]
private void RespondTimerStateClientRpc(float timeRemaining, bool timerActive, ulong clientId)
{
if (NetworkManager.Singleton.LocalClientId == clientId)
{
_timerText.enabled = timerActive;
_timerText.text = $"Starting Game in {Mathf.Ceil(timeRemaining)}";
}
}
// [SerializeField] private GameObject keyPrefab;
// [SerializeField] private bool startGame;
// private TextMeshProUGUI _timerText;
// private float _initialTimer = 10f;
// private float _startGameTimer = 10f;
// private bool _initialTimerActive = true;
// private bool _startGameTimerActive;
//
//
// private void Start()
// {
// _timerText = GameObject.Find("Start_Game").GetComponent<TextMeshProUGUI>();
// if (_timerText == null)
// {
// Debug.LogError("TextMeshPro component not found on Start Game GameObject!");
// return;
// }
//
// if (IsServer)
// {
// // _initialTimerActive = startGame;
// }
//
// _initialTimerActive = startGame;
// }
//
// private void Update()
// {
// if (!IsServer) return;
//
// if (_initialTimerActive)
// {
// _initialTimer -= Time.deltaTime;
// if (_initialTimer <= 0)
// {
// _initialTimerActive = false;
// _startGameTimerActive = true;
// EnableTimerTextClientRpc(true);
// }
// }
//
// if (_startGameTimerActive)
// {
// _startGameTimer -= Time.deltaTime;
// if (_startGameTimer > 0)
// {
// UpdateTimerClientRpc(_startGameTimer);
// }
// else
// {
// _startGameTimerActive = false;
// UpdateTimerClientRpc(0);
// EnableTimerTextClientRpc(false);
// TimersEndedServerRpc();
// }
// }
// }
//
// [ClientRpc]
// private void UpdateTimerClientRpc(float timeRemaining)
// {
// if (_timerText != null)
// {
// _timerText.text = $"Starting Game in {Mathf.Ceil(timeRemaining)}";
// }
// }
//
// [ClientRpc]
// private void EnableTimerTextClientRpc(bool state)
// {
// if (_timerText != null)
// {
// _timerText.enabled = state;
// }
// }
//
// [ServerRpc]
// private void TimersEndedServerRpc()
// {
// for (int i = 0; i < 2; i++)
// {
// Vector3 spawnPosition = new Vector3(10 + UnityEngine.Random.Range(-5f, 5f), 0,
// 10 + Random.Range(-5f, 5f));
// GameObject obj = Instantiate(keyPrefab, spawnPosition, Quaternion.identity);
// obj.GetComponent<NetworkObject>().Spawn();
// }
// }
//
//
// [ServerRpc(RequireOwnership = false)]
// public void RequestTimerStateServerRpc(ServerRpcParams rpcParams = default)
// {
// if (_initialTimerActive)
// {
// RespondTimerStateClientRpc(_initialTimer, true, rpcParams.Receive.SenderClientId);
// }
// else if (_startGameTimerActive)
// {
// RespondTimerStateClientRpc(_startGameTimer, true, rpcParams.Receive.SenderClientId);
// }
// else
// {
// RespondTimerStateClientRpc(0, false, rpcParams.Receive.SenderClientId);
// }
// }
//
// [ClientRpc]
// private void RespondTimerStateClientRpc(float timeRemaining, bool timerActive, ulong clientId)
// {
// if (NetworkManager.Singleton.LocalClientId == clientId)
// {
// _timerText.enabled = timerActive;
// _timerText.text = $"Starting Game in {Mathf.Ceil(timeRemaining)}";
// }
// }
}
\ No newline at end of file
using UnityEngine;
/// <summary>
/// Manages player-related functionality, including input handling and player events.
/// </summary>
public class PlayerManager : MonoBehaviour
{
/// <summary>
/// Handles player input and provides input data to other systems.
/// </summary>
public InputReader inputReader;
/// <summary>
/// Handles events related to player actions such as movement, interaction, and combat.
/// </summary>
public PlayerEvents playerEvents;
/// <summary>
/// Initializes the PlayerManager by setting up input handling and player events.
/// </summary>
public void Initialize()
{
inputReader.InitializeInput();
......
......@@ -5,18 +5,23 @@ using TMPro;
using Unity.Netcode;
using UnityEngine;
/// <summary>
/// Manages the respawn process for players, including UI updates, countdowns, and player reinitialization.
/// </summary>
public class RespawnManager : NetworkBehaviour
{
[SerializeField] private GameObject _respawnPlayerPanel;
[SerializeField] private TextMeshProUGUI _countdownTimeText;
[SerializeField] private int _playerDeadLayer = 11;
public static RespawnManager Instance { get; private set; }
private int _respawnTime = 10;
private int _health = 100;
private Coroutine _countdownCoroutine;
[SerializeField] private GameObject _respawnPlayerPanel; // UI panel displayed during respawn countdown.
[SerializeField] private TextMeshProUGUI _countdownTimeText; // Text element for displaying countdown time.
[SerializeField] private int _playerDeadLayer = 11; // Layer assigned to players during respawn.
public static RespawnManager Instance { get; private set; } // Singleton instance of the RespawnManager.
private int _respawnTime = 10; // Time (in seconds) for the respawn countdown.
private int _health = 100; // Initial health value for respawned players.
private Coroutine _countdownCoroutine; // Reference to the active countdown coroutine.
/// <summary>
/// Ensures only one instance of RespawnManager exists and persists across scenes.
/// </summary>
private void Awake()
{
if (Instance == null)
......@@ -29,6 +34,10 @@ public class RespawnManager : NetworkBehaviour
}
}
/// <summary>
/// Initiates the respawn process for a player, including disabling controls and starting the countdown.
/// </summary>
/// <param name="player">The player GameObject to respawn.</param>
public void StartRespawnPlayer(GameObject player)
{
if (IsServer)
......@@ -45,6 +54,10 @@ public class RespawnManager : NetworkBehaviour
}
}
/// <summary>
/// Disables player controls for the specified client.
/// </summary>
/// <param name="clientId">The ID of the client whose controls should be disabled.</param>
[ClientRpc]
private void TurnOffPlayerControlsClientRpc(ulong clientId)
{
......@@ -59,6 +72,10 @@ public class RespawnManager : NetworkBehaviour
}
}
/// <summary>
/// Displays the respawn UI and starts the countdown for the specified client.
/// </summary>
/// <param name="clientId">The ID of the client to show the respawn UI for.</param>
[ClientRpc]
private void ShowRespawnUIClientRpc(ulong clientId)
{
......@@ -72,6 +89,9 @@ public class RespawnManager : NetworkBehaviour
}
}
/// <summary>
/// Handles the respawn countdown and triggers player respawn when the countdown ends.
/// </summary>
private IEnumerator RespawnCountdownCoroutine()
{
int currentTime = _respawnTime;
......@@ -99,6 +119,10 @@ public class RespawnManager : NetworkBehaviour
}
}
/// <summary>
/// Despawns the player object for the specified client.
/// </summary>
/// <param name="clientId">The ID of the client whose player object should be despawned.</param>
[ServerRpc(RequireOwnership = false)]
private void DespawnPlayerServerRpc(ulong clientId)
{
......@@ -112,7 +136,10 @@ public class RespawnManager : NetworkBehaviour
playerNetworkObjectToRemove.Despawn();
}
/// <summary>
/// Spawns a new player object for the specified client and reinitializes its state.
/// </summary>
/// <param name="clientId">The ID of the client to spawn a new player for.</param>
[ServerRpc(RequireOwnership = false)]
private void RequestSpawnPlayerServerRpc(ulong clientId)
{
......
......@@ -2,12 +2,22 @@ using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
/// <summary>
/// Manages the targeting system for enemies, allowing them to detect and target players within a specified radius.
/// </summary>
public class TargetingManager : NetworkBehaviour
{
/// <summary>
/// Singleton instance of the TargetingManager.
/// </summary>
public static TargetingManager Instance { get; private set; }
private Collider[] playerColliders;
private List<Enemy> enemies = new List<Enemy>();
private Collider[] playerColliders; // Array to store colliders of detected players.
private List<Enemy> enemies = new List<Enemy>(); // List of enemies managed by the targeting system.
/// <summary>
/// Called when the object is spawned on the network. Initializes player colliders on the server.
/// </summary>
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
......@@ -17,6 +27,9 @@ public class TargetingManager : NetworkBehaviour
}
}
/// <summary>
/// Updates the targeting system every frame. Searches for players in the detection radius of each enemy.
/// </summary>
private void Update()
{
if (IsServer)
......@@ -25,20 +38,27 @@ public class TargetingManager : NetworkBehaviour
}
}
/// <summary>
/// Searches for players within the detection radius of each enemy and assigns the closest player as the target.
/// </summary>
private void SearchForPlayersInEnemyRadius()
{
foreach (var enemy in enemies)
{
if (enemy != null)
{
int numColliders = Physics.OverlapSphereNonAlloc(enemy.transform.position,
int numColliders = Physics.OverlapSphereNonAlloc(
enemy.transform.position,
enemy.DetectionRadius,
playerColliders, enemy.TargetLayerMask);
playerColliders,
enemy.TargetLayerMask
);
if (numColliders > 0)
{
Transform closestPlayer = null;
float closestDistanceSqr = Mathf.Infinity;
for (int i = 0; i < numColliders; i++)
{
float distanceSqr = (playerColliders[i].transform.position - enemy.transform.position)
......@@ -61,16 +81,27 @@ public class TargetingManager : NetworkBehaviour
}
}
/// <summary>
/// Adds an enemy to the targeting system's list of managed enemies.
/// </summary>
/// <param name="enemy">The enemy to add.</param>
public void AddEnemyToTargetingList(Enemy enemy)
{
enemies.Add(enemy);
}
/// <summary>
/// Removes an enemy from the targeting system's list of managed enemies.
/// </summary>
/// <param name="enemy">The enemy to remove.</param>
public void RemoveEnemyFromTargetingList(Enemy enemy)
{
enemies.Remove(enemy);
}
/// <summary>
/// Ensures only one instance of TargetingManager exists and persists across scenes.
/// </summary>
private void Awake()
{
if (Instance != null && Instance != this)
......
......@@ -2,15 +2,24 @@ using System;
using UnityEngine;
using UnityEngine.UIElements;
/// <summary>
/// Represents an arrow that can follow a target's position and rotation.
/// </summary>
public class Arrow : MonoBehaviour
{
private Transform _targetTransform;
private Transform _targetTransform; // The transform of the target the arrow will follow.
/// <summary>
/// Updates the arrow's position and rotation to follow the target.
/// </summary>
private void Update()
{
FollowTarget();
}
/// <summary>
/// Makes the arrow follow the target's position and rotation.
/// </summary>
private void FollowTarget()
{
if (_targetTransform != null)
......@@ -20,11 +29,18 @@ public class Arrow : MonoBehaviour
}
}
/// <summary>
/// Sets the target transform for the arrow to follow.
/// </summary>
/// <param name="targetTransform">The transform of the target.</param>
public void SetTargetTransform(Transform targetTransform)
{
_targetTransform = targetTransform;
}
/// <summary>
/// Removes the target transform, stopping the arrow from following it.
/// </summary>
public void RemoveTargetTransform()
{
_targetTransform = null;
......
using DG.Tweening;
using UnityEngine;
/// <summary>
/// Handles the movement and rotation of a GameObject to follow a target transform or player controls.
/// </summary>
public class FollowTransform : MonoBehaviour
{
private ISwitchPlayerMap _targetPlayerControls;
private Transform _targetTransform;
private Quaternion _startingRotation;
private ISwitchPlayerMap _targetPlayerControls; // Interface for managing player control states.
private Transform _targetTransform; // The transform to follow.
private Quaternion _startingRotation; // The initial rotation of the GameObject.
[SerializeField]
private FollowTransformSettings followTransformSettings; // Settings for movement and rotation behavior.
[SerializeField] private FollowTransformSettings followTransformSettings;
/// <summary>
/// Initializes the starting rotation of the GameObject.
/// </summary>
private void Start()
{
_startingRotation = transform.rotation;
}
/// <summary>
/// Sets the target player controls to manage during the follow process.
/// </summary>
/// <param name="targetPlayerControls">The player controls to manage.</param>
public void SetTargetPlayerControls(ISwitchPlayerMap targetPlayerControls)
{
this._targetPlayerControls = targetPlayerControls;
}
/// <summary>
/// Sets the target transform for the GameObject to follow.
/// </summary>
/// <param name="targetTransform">The transform to follow.</param>
public void SetTargetTransform(Transform targetTransform)
{
if (targetTransform != null)
......@@ -33,6 +47,10 @@ public class FollowTransform : MonoBehaviour
}
}
/// <summary>
/// Removes the target transform and moves the GameObject to a specified position.
/// </summary>
/// <param name="putDownPosition">The position to move the GameObject to.</param>
public void RemoveTargetTransform(Vector3 putDownPosition)
{
_targetPlayerControls.TurnOffPlayerControls();
......@@ -45,6 +63,9 @@ public class FollowTransform : MonoBehaviour
});
}
/// <summary>
/// Updates the GameObject's position and rotation to match the target transform.
/// </summary>
private void LateUpdate()
{
if (_targetTransform == null)
......
using Unity.Netcode.Components;
/// <summary>
/// A custom implementation of NetworkAnimator that allows client authority over animation synchronization.
/// </summary>
public class OwnerNetworkAnimator : NetworkAnimator
{
/// <summary>
/// Determines whether the server is authoritative for this animator.
/// This implementation makes the owner client authoritative instead of the server.
/// </summary>
/// <returns>False, indicating that the owner client is authoritative.</returns>
protected override bool OnIsServerAuthoritative()
{
return false;
......
using Unity.Netcode;
using UnityEngine;
/// <summary>
/// Handles player animation states and synchronizes them with player events.
/// </summary>
public class PlayerAnimator : NetworkBehaviour
{
private const string IS_WALKING = "IsWalking";
private const string IS_RUNNING = "IsRunning";
private const string IS_INTERACTING = "Interact";
private const string IS_ATTACKING = "Attack";
private const string IS_DEFENDING = "IsDefending";
private const string IS_WALKING = "IsWalking"; // Animation parameter for walking state.
private const string IS_RUNNING = "IsRunning"; // Animation parameter for running state.
private const string IS_INTERACTING = "Interact"; // Animation trigger for interaction.
private const string IS_ATTACKING = "Attack"; // Animation trigger for attacking.
private const string IS_DEFENDING = "IsDefending"; // Animation parameter for defending state.
private PlayerEvents _playerEvents; // Reference to player events for subscribing to animation triggers.
private Animator _animator; // Reference to the Animator component.
private PlayerEvents _playerEvents;
private Animator _animator;
/// <summary>
/// Initializes the Animator component.
/// </summary>
private void Start()
{
_animator = GetComponentInChildren<Animator>();
}
/// <summary>
/// Unsubscribes from player events when the object is disabled.
/// </summary>
private void OnDisable()
{
if (_playerEvents != null)
......@@ -31,6 +38,10 @@ public class PlayerAnimator : NetworkBehaviour
}
}
/// <summary>
/// Subscribes to player events to handle animation state changes.
/// </summary>
/// <param name="playerEvents">The PlayerEvents instance to subscribe to.</param>
public void InitializeEvents(PlayerEvents playerEvents)
{
this._playerEvents = playerEvents;
......@@ -44,27 +55,44 @@ public class PlayerAnimator : NetworkBehaviour
}
}
/// <summary>
/// Sets the running animation state.
/// </summary>
/// <param name="state">True if the player is running, false otherwise.</param>
private void SetPlayerRunBool(bool state)
{
_animator.SetBool(IS_RUNNING, state);
}
/// <summary>
/// Sets the walking animation state.
/// </summary>
/// <param name="state">True if the player is walking, false otherwise.</param>
private void SetPlayerWalkBool(bool state)
{
_animator.SetBool(IS_WALKING, state);
}
/// <summary>
/// Triggers the interaction animation.
/// </summary>
private void SetPlayerInteract()
{
_animator.CrossFade(IS_INTERACTING, 0.1f, -1, 0, 1f);
}
/// <summary>
/// Triggers the attack animation.
/// </summary>
private void SetPlayerAttack()
{
_animator.CrossFade(IS_ATTACKING, 0.1f, -1, 0, 1f);
}
/// <summary>
/// Sets the defending animation state.
/// </summary>
/// <param name="state">True if the player is defending, false otherwise.</param>
private void SetPlayerDefence(bool state)
{
_animator.SetBool(IS_DEFENDING, state);
......
......@@ -2,14 +2,24 @@ using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Manages the player's health, including health bar updates and respawn logic.
/// </summary>
public class PlayerHealth : NetworkBehaviour
{
[SerializeField] private GameObject _healthCanvas;
private Slider _healthSlider;
private NetworkVariable<int> playerHealth = new NetworkVariable<int>();
private Vector3 _healthBarOffset;
private bool isRespawning;
[SerializeField] private GameObject _healthCanvas; // The canvas displaying the player's health bar.
private Slider _healthSlider; // The slider component representing the health bar.
private NetworkVariable<int>
playerHealth = new NetworkVariable<int>(); // The player's health value synchronized across the network.
private Vector3 _healthBarOffset; // Offset for positioning the health bar above the player.
private bool isRespawning; // Tracks whether the player is currently respawning.
/// <summary>
/// Called when the object is spawned on the network.
/// Initializes the health bar and its position.
/// </summary>
public override void OnNetworkSpawn()
{
_healthBarOffset = _healthCanvas.transform.localPosition;
......@@ -17,13 +27,10 @@ public class PlayerHealth : NetworkBehaviour
_healthSlider = _healthCanvas.GetComponentInChildren<Slider>();
}
[ClientRpc]
private void StartHealthBarClientRpc(int health)
{
_healthSlider.maxValue = health;
}
/// <summary>
/// Initializes the player's health and starts the health bar.
/// </summary>
/// <param name="health">The initial health value.</param>
public void InitializePlayerHealth(int health)
{
if (IsServer)
......@@ -34,12 +41,19 @@ public class PlayerHealth : NetworkBehaviour
}
}
/// <summary>
/// Updates the health bar's position and value.
/// </summary>
private void Update()
{
_healthCanvas.transform.position = gameObject.transform.position + _healthBarOffset;
_healthSlider.value = playerHealth.Value;
}
/// <summary>
/// Decreases the player's health and triggers respawn if health reaches zero.
/// </summary>
/// <param name="health">The amount of health to decrease.</param>
public void decreaseHealth(int health)
{
if (IsServer)
......@@ -54,34 +68,19 @@ public class PlayerHealth : NetworkBehaviour
}
}
// [ClientRpc]
// private void UpdateHealthClientRpc(int curHealth)
// {
// _healthSlider.value = curHealth;
// }
/// <summary>
/// Starts the health bar on the client with the specified maximum health.
/// </summary>
/// <param name="health">The maximum health value.</param>
[ClientRpc]
private void StartHealthBarClientRpc(int health)
{
_healthSlider.maxValue = health;
}
// private void OnDestroy()
// {
// if (IsServer)
// {
// Destroy(_healthCanvas);
//
// DestroyHealthBarClientRpc();
// }
// }
//
// [ClientRpc]
// private void DestroyHealthBarClientRpc()
// {
// if (_healthCanvas != null)
// {
// Destroy(_healthCanvas);
// }
// else
// {
// Debug.LogError("Cant find canvas");
// }
// }
/// <summary>
/// Initiates the destruction of the health bar on all clients.
/// </summary>
[ClientRpc]
public void InitiateHealthBarDestructionClientRpc()
{
......
......@@ -2,21 +2,26 @@ using System;
using UnityEngine;
using UnityEngine.InputSystem;
/// <summary>
/// Handles player input using Unity's Input System and provides events for various player actions.
/// </summary>
[CreateAssetMenu(fileName = "InputReader", menuName = "Scriptable Objects/InputReader")]
public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions, IInputHandler, ISwitchPlayerMap
{
private InputSystem_Actions inputActions;
public event Action<Vector2> MoveEvent;
public event Action<Vector2> LookEvent;
public event Action InteractEvent;
public event Action JumpEvent;
public event Action AttackEvent;
public event Action<bool> SprintEvent;
public event Action<bool> CrouchEvent;
public event Action<bool> DefenceEvent;
private InputSystem_Actions inputActions; // Input actions generated by Unity's Input System.
public event Action<Vector2> MoveEvent; // Event triggered when the player moves.
public event Action<Vector2> LookEvent; // Event triggered when the player looks around.
public event Action InteractEvent; // Event triggered when the player interacts.
public event Action JumpEvent; // Event triggered when the player jumps.
public event Action AttackEvent; // Event triggered when the player attacks.
public event Action<bool> SprintEvent; // Event triggered when the player sprints.
public event Action<bool> CrouchEvent; // Event triggered when the player crouches.
public event Action<bool> DefenceEvent; // Event triggered when the player defends.
/// <summary>
/// Initializes the input system and sets up callbacks for player actions.
/// </summary>
public void InitializeInput()
{
if (inputActions == null)
......@@ -28,6 +33,9 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
inputActions.Enable();
}
/// <summary>
/// Disables the input system when the object is disabled.
/// </summary>
private void OnDisable()
{
if (inputActions != null)
......@@ -38,6 +46,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles movement input and triggers the MoveEvent.
/// </summary>
/// <param name="context">The input context for movement.</param>
public void OnMove(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -50,6 +62,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles look input and triggers the LookEvent.
/// </summary>
/// <param name="context">The input context for looking.</param>
public void OnLook(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -62,6 +78,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles attack input and triggers the AttackEvent.
/// </summary>
/// <param name="context">The input context for attacking.</param>
public void OnAttack(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -70,6 +90,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles defence input and triggers the DefenceEvent.
/// </summary>
/// <param name="context">The input context for defending.</param>
public void OnDefence(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -82,6 +106,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles interaction input and triggers the InteractEvent.
/// </summary>
/// <param name="context">The input context for interacting.</param>
public void OnInteract(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -90,6 +118,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles crouch input and triggers the CrouchEvent.
/// </summary>
/// <param name="context">The input context for crouching.</param>
public void OnCrouch(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -102,6 +134,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles jump input and triggers the JumpEvent.
/// </summary>
/// <param name="context">The input context for jumping.</param>
public void OnJump(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -110,6 +146,10 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Handles sprint input and triggers the SprintEvent.
/// </summary>
/// <param name="context">The input context for sprinting.</param>
public void OnSprint(InputAction.CallbackContext context)
{
if (context.performed)
......@@ -122,26 +162,43 @@ public class InputReader : ScriptableObject, InputSystem_Actions.IPlayerActions,
}
}
/// <summary>
/// Simulates movement input (not implemented).
/// </summary>
/// <param name="movement">The movement vector to simulate.</param>
public void SimulateMove(Vector2 movement)
{
throw new NotImplementedException();
}
/// <summary>
/// Simulates interaction input (not implemented).
/// </summary>
public void SimulateInteract()
{
throw new NotImplementedException();
}
/// <summary>
/// Simulates sprint input (not implemented).
/// </summary>
/// <param name="isSprinting">True if sprinting, false otherwise.</param>
public void SimulateSprint(bool isSprinting)
{
throw new NotImplementedException();
}
/// <summary>
/// Disables player controls by disabling the input actions.
/// </summary>
public void TurnOffPlayerControls()
{
inputActions.Player.Disable();
}
/// <summary>
/// Enables player controls by enabling the input actions.
/// </summary>
public void TurnOnPlayerControls()
{
inputActions.Player.Enable();
......
......@@ -15,7 +15,7 @@ GameObject:
- component: {fileID: 3234479000206332123}
- component: {fileID: 5394816119229616792}
- component: {fileID: 2649082171887839502}
- component: {fileID: 6070314325824568771}
- component: {fileID: 8688275168607712535}
m_Layer: 10
m_Name: Cube
m_TagString: Untagged
......@@ -179,7 +179,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
enemySettings: {fileID: 11400000, guid: 9fdb93bec43a5104295cc3583f523a20, type: 2}
--- !u!114 &6070314325824568771
--- !u!114 &8688275168607712535
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
......
......@@ -9,6 +9,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 5647974449618258513}
- component: {fileID: 8466409412588946250}
m_Layer: 0
m_Name: EnemySpawnLocations
m_TagString: Untagged
......@@ -25,7 +26,7 @@ Transform:
m_GameObject: {fileID: 354072136138752549}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalPosition: {x: 0, y: 0.2, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
......@@ -35,6 +36,19 @@ Transform:
- {fileID: 5019612241553091319}
m_Father: {fileID: 3251327355353088423}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8466409412588946250
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 354072136138752549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a22d62560c8f61a4fbd55236631e8334, type: 3}
m_Name:
m_EditorClassIdentifier:
radius: 5
--- !u!1 &381795952518723057
GameObject:
m_ObjectHideFlags: 0
......@@ -123,7 +137,7 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 728568152667097525}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
......@@ -152,7 +166,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &5581542974833947271
Transform:
m_ObjectHideFlags: 0
......@@ -162,7 +176,7 @@ Transform:
m_GameObject: {fileID: 1342101318069946295}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalPosition: {x: 0, y: 0.2, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
......@@ -215,7 +229,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &5001222007940412494
Transform:
m_ObjectHideFlags: 0
......@@ -225,7 +239,7 @@ Transform:
m_GameObject: {fileID: 5250389714568146909}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalPosition: {x: 0, y: 0.7, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
......@@ -247,7 +261,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &2438670058733636552
Transform:
m_ObjectHideFlags: 0
......@@ -368,7 +382,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &5981432708657565925
Transform:
m_ObjectHideFlags: 0
......@@ -400,7 +414,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &1806774946114198236
Transform:
m_ObjectHideFlags: 0
......@@ -410,7 +424,7 @@ Transform:
m_GameObject: {fileID: 7584320928867012029}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalPosition: {x: 0, y: 0.9, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
......@@ -458,7 +472,7 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 163114042722539874, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: GlobalObjectIdHash
value: 3307046875
value: 2546934904
objectReference: {fileID: 0}
- target: {fileID: 163114042722539874, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: InScenePlacedSourceGlobalObjectIdHash
......@@ -1708,7 +1722,7 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 1580681325717503087, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: GlobalObjectIdHash
value: 1549677047
value: 1793678996
objectReference: {fileID: 0}
- target: {fileID: 4727207244663773237, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_Name
......@@ -1870,7 +1884,7 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 1580681325717503087, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: GlobalObjectIdHash
value: 1334992784
value: 2157953702
objectReference: {fileID: 0}
- target: {fileID: 4727207244663773237, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_Name
......@@ -2152,7 +2166,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 2408943373
GlobalObjectIdHash: 1212816001
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
......@@ -2630,7 +2644,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 3719657908984160168, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: GlobalObjectIdHash
value: 870031014
value: 745029092
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
......@@ -2656,7 +2670,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalPosition.y
value: 0.5
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalPosition.z
......@@ -2692,7 +2706,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 3668773499323874180, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: GlobalObjectIdHash
value: 2909008999
value: 2706695298
objectReference: {fileID: 0}
- target: {fileID: 8050255731901760503, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_Name
......
......@@ -10,6 +10,7 @@ GameObject:
m_Component:
- component: {fileID: 1774531537854147144}
- component: {fileID: 2847495381736913473}
- component: {fileID: -3393537255742368440}
m_Layer: 0
m_Name: EnemySpawner
m_TagString: Untagged
......@@ -48,6 +49,31 @@ MonoBehaviour:
ShowTopMostFoldoutHeaderGroup: 1
_rogueEnemyPrefab: {fileID: 0}
_slimeEnemyPrefab: {fileID: 0}
--- !u!114 &-3393537255742368440
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6866275124911934084}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 2930372943
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 1
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
SyncOwnerTransformWhenParented: 1
AllowOwnerToParent: 0
--- !u!1 &7258924596401886573
GameObject:
m_ObjectHideFlags: 0
......
......@@ -47,7 +47,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 2107378644
GlobalObjectIdHash: 1523420517
InScenePlacedSourceGlobalObjectIdHash: 389880154
DeferredDespawnTick: 0
Ownership: 1
......@@ -161,6 +161,14 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 7801895876235266027}
m_Modifications:
- target: {fileID: -3393537255742368440, guid: 97ac290fc57dc044a9e439c8e5a05a23, type: 3}
propertyPath: GlobalObjectIdHash
value: 1523420517
objectReference: {fileID: 0}
- target: {fileID: -3393537255742368440, guid: 97ac290fc57dc044a9e439c8e5a05a23, type: 3}
propertyPath: InScenePlacedSourceGlobalObjectIdHash
value: 389880154
objectReference: {fileID: 0}
- target: {fileID: 941907791769148275, guid: 97ac290fc57dc044a9e439c8e5a05a23, type: 3}
propertyPath: GlobalObjectIdHash
value: 3612224711
......@@ -171,7 +179,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 1774531537854147144, guid: 97ac290fc57dc044a9e439c8e5a05a23, type: 3}
propertyPath: m_LocalPosition.y
value: 0.5603608
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1774531537854147144, guid: 97ac290fc57dc044a9e439c8e5a05a23, type: 3}
propertyPath: m_LocalPosition.z
......
......@@ -111,7 +111,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 2011270040
GlobalObjectIdHash: 3486418551
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
......
......@@ -333,12 +333,11 @@ MonoBehaviour:
RangerAmountContainer: {fileID: 1018751068}
SlimeAmountContainer: {fileID: 1544296584}
_connectButton: {fileID: 251032852}
_gameStartCountDownTime: 2
_slimeSpawnCooldownTime: 0.01
_rogueSpawnCooldownTime: 0.3
playerPrefab: {fileID: 7039287367920326276, guid: 702bb31d143eeaa4792be36b28160445, type: 3}
playerHealth: 100
_slimeSpawnCooldownTime: 1
_rogueSpawnCooldownTime: 2
_startGameCountdownTimer: 10
playerPrefab: {fileID: 7039287367920326276, guid: 702bb31d143eeaa4792be36b28160445, type: 3}
playerHealth: 200
--- !u!114 &529219308
MonoBehaviour:
m_ObjectHideFlags: 0
......@@ -653,6 +652,10 @@ PrefabInstance:
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 309593061376755853, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_text
value: "4\u200B"
objectReference: {fileID: 0}
- target: {fileID: 920270909126316112, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_AnchorMax.y
value: 0
......@@ -781,6 +784,10 @@ PrefabInstance:
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3534326167216121825, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_Text
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4034502693420905108, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_AnchorMax.y
value: 0
......@@ -869,6 +876,10 @@ PrefabInstance:
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5737202750316455812, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_Text
value: 127.0.0.1
objectReference: {fileID: 0}
- target: {fileID: 5802551866461339365, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_AnchorMax.y
value: 0
......
......@@ -581,24 +581,6 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1538239691 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 354072136138752549, guid: 2533a95934a9ea044a5454189730090b, type: 3}
m_PrefabInstance: {fileID: 4656849397191549919}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1538239693
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1538239691}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a22d62560c8f61a4fbd55236631e8334, type: 3}
m_Name:
m_EditorClassIdentifier:
radius: 5
--- !u!1 &1594659819
GameObject:
m_ObjectHideFlags: 0
......@@ -990,14 +972,6 @@ PrefabInstance:
propertyPath: m_Name
value: Environment
objectReference: {fileID: 0}
- target: {fileID: 1342101318069946295, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1806774946114198236, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_LocalPosition.y
value: 0.9
objectReference: {fileID: 0}
- target: {fileID: 2571745861886921497, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: GlobalObjectIdHash
value: 2157953702
......@@ -1046,46 +1020,14 @@ PrefabInstance:
propertyPath: GlobalObjectIdHash
value: 1793678996
objectReference: {fileID: 0}
- target: {fileID: 5001222007940412494, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_LocalPosition.y
value: 0.7
objectReference: {fileID: 0}
- target: {fileID: 5250389714568146909, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5281452119083837664, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: GlobalObjectIdHash
value: 1212816001
objectReference: {fileID: 0}
- target: {fileID: 5510887720992502651, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5581542974833947271, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_LocalPosition.y
value: 0.2
objectReference: {fileID: 0}
- target: {fileID: 5647974449618258513, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_LocalPosition.y
value: 0.2
objectReference: {fileID: 0}
- target: {fileID: 5718679709133256066, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7270026267180335326, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: GlobalObjectIdHash
value: 745029092
objectReference: {fileID: 0}
- target: {fileID: 7466567691796396836, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7584320928867012029, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7679692720847302870, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: GlobalObjectIdHash
value: 2706695298
......@@ -1093,10 +1035,7 @@ PrefabInstance:
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 354072136138752549, guid: 2533a95934a9ea044a5454189730090b, type: 3}
insertIndex: -1
addedObject: {fileID: 1538239693}
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 2533a95934a9ea044a5454189730090b, type: 3}
--- !u!1001 &6950935288098905811
PrefabInstance:
......@@ -1106,10 +1045,6 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 4464205841933766465, guid: c3c6003d148e24045a5699c460b258c9, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4994959905079220019, guid: c3c6003d148e24045a5699c460b258c9, type: 3}
propertyPath: m_Name
value: Managers
......@@ -1166,6 +1101,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8481359329700982849, guid: c3c6003d148e24045a5699c460b258c9, type: 3}
propertyPath: GlobalObjectIdHash
value: 3413010678
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
......
......@@ -15,7 +15,7 @@ MonoBehaviour:
targetLayer:
serializedVersion: 2
m_Bits: 512
detectionRange: 80
shootingRange: 15
detectionRange: 13
shootingRange: 25
shootingDelay: 5
speed: 0
......@@ -15,7 +15,7 @@ MonoBehaviour:
targetLayer:
serializedVersion: 2
m_Bits: 512
detectionRange: 80
detectionRange: 10
shootingRange: 0
shootingDelay: 0
speed: 5
speed: 4
using System;
using UnityEngine;
/// <summary>
/// A singleton configuration class for managing game data related to enemy amounts and spawn timers.
/// </summary>
public class GameDataConfig : MonoBehaviour
{
/// <summary>
/// The singleton instance of the GameDataConfig class.
/// </summary>
public static GameDataConfig Instance { get; private set; }
/// <summary>
/// The number of rogue enemies in the game.
/// </summary>
public int RogueEnemyAmount;
/// <summary>
/// The number of slime enemies in the game.
/// </summary>
public int SlimeEnemyAmount;
public float RogueEnemySpawnTimer = 2f;
public float SlimeEnemySpawnTimer = 0.5f;
/// <summary>
/// The spawn timer for rogue enemies.
/// </summary>
public float RogueEnemySpawnTimer;
/// <summary>
/// The spawn timer for slime enemies.
/// </summary>
public float SlimeEnemySpawnTimer;
/// <summary>
/// Ensures that only one instance of the GameDataConfig class exists.
/// If another instance is found, it is destroyed.
/// </summary>
private void Awake()
{
if (Instance != null && Instance != this)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment