diff --git a/Assets/GameFlowManager.cs b/Assets/GameFlowManager.cs new file mode 100644 index 0000000..792f185 --- /dev/null +++ b/Assets/GameFlowManager.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +//Could be a singleton +public class GameFlowManager : MonoBehaviour { + [field: SerializeField] public bool Paused { get; private set; } = true; + + void SetPause(bool value) { + Paused = value; + Time.timeScale = value ? 0f : 1f; + } +} \ No newline at end of file diff --git a/Assets/GameFlowManager.cs.meta b/Assets/GameFlowManager.cs.meta new file mode 100644 index 0000000..17ff82d --- /dev/null +++ b/Assets/GameFlowManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3fecdc4a8b2cb4419ef9d03180d130d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 236943a..762f234 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -200,6 +200,10 @@ PrefabInstance: m_Modification: m_TransformParent: {fileID: 0} m_Modifications: + - target: {fileID: -7596782781093632548, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3} + propertyPath: gameFlowManager + value: + objectReference: {fileID: 1359990806} - target: {fileID: 9196727425507610130, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3} propertyPath: m_RootOrder value: 2 @@ -250,6 +254,24 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3} +--- !u!1 &1359990805 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 9196727425507610131, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3} + m_PrefabInstance: {fileID: 1359990804} + m_PrefabAsset: {fileID: 0} +--- !u!114 &1359990806 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1359990805} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e3fecdc4a8b2cb4419ef9d03180d130d, type: 3} + m_Name: + m_EditorClassIdentifier: + k__BackingField: 1 --- !u!114 &1464970062 stripped MonoBehaviour: m_CorrespondingSourceObject: {fileID: 1878107874314509256, guid: e1dac4f28fe75a547b919b7aa8240fed, type: 3} @@ -424,6 +446,10 @@ PrefabInstance: propertyPath: m_ActionEvents.Array.data[13].m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName value: UnityEngine.Object, UnityEngine objectReference: {fileID: 0} + - target: {fileID: 1214567908930553592, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3} + propertyPath: gameFlowManager + value: + objectReference: {fileID: 1359990806} - target: {fileID: 1214567908930553593, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3} propertyPath: m_Name value: Vampire @@ -480,6 +506,10 @@ PrefabInstance: propertyPath: healthBar value: objectReference: {fileID: 1464970062} + - target: {fileID: 3126145803593047825, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3} + propertyPath: gameFlowManager + value: + objectReference: {fileID: 1359990806} - target: {fileID: 3126145803593047825, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3} propertyPath: k__BackingField value: 100 diff --git a/Assets/Scripts/Arena.cs b/Assets/Scripts/Arena.cs index d6a18ac..da1bc49 100644 --- a/Assets/Scripts/Arena.cs +++ b/Assets/Scripts/Arena.cs @@ -4,8 +4,12 @@ using NaughtyAttributes; using UnityEngine; public class Arena : MonoBehaviour { - //TODO probably add initial direction too [SerializeField] [Required] + GameFlowManager gameFlowManager = null!; + + //TODO probably add initial direction too + //TODO Add some kind of "MinLength(1)" attribute + [SerializeField] Vector3[] spawners = null!; [SerializeField] [Required] ArenaStats stats = null!; @@ -19,6 +23,9 @@ public class Arena : MonoBehaviour { void Start() => StartCoroutine(SpawnEnemies()); void SpawnEnemy(int spawnerIndex) { + if (gameFlowManager.Paused) + return; + var monster = Instantiate(monsterPrefab, spawners[spawnerIndex], Quaternion.identity).GetComponent(); //TODO Replace hardcoded target with entity discovery monster.SetTarget(FindObjectOfType().transform); @@ -29,11 +36,10 @@ public class Arena : MonoBehaviour { int currentSpawner = 0; - //TODO Stop when pause/end game while (true) { SpawnEnemy(currentSpawner); currentSpawner = Random.Range(0, spawners.Length); - yield return new WaitForSeconds(stats.secondsBetweenSpawners); + yield return new WaitForSeconds(stats.secondsBetweenSpawners); } } diff --git a/Assets/Scripts/Entity.cs b/Assets/Scripts/Entity.cs index 891e2af..a6fec90 100644 --- a/Assets/Scripts/Entity.cs +++ b/Assets/Scripts/Entity.cs @@ -6,6 +6,9 @@ using UnityEngine; [RequireComponent(typeof(Rigidbody2D))] public class Entity : MonoBehaviour { + [SerializeField] [Required] + GameFlowManager gameFlowManager = null!; + [field: SerializeField] [field: Required] protected EntityStats stats { get; private set; } [field: SerializeField]protected float Health { get; private set; } diff --git a/Assets/Scripts/PlayerMovement.cs b/Assets/Scripts/PlayerMovement.cs index 4b623b0..84dd8f6 100644 --- a/Assets/Scripts/PlayerMovement.cs +++ b/Assets/Scripts/PlayerMovement.cs @@ -5,33 +5,48 @@ using UnityEngine.InputSystem; [RequireComponent(typeof(PlayerInput), typeof(Rigidbody2D))] public class PlayerMovement : MonoBehaviour { + [SerializeField] [Required] + GameFlowManager gameFlowManager = null!; + [SerializeField] [field: Required] PlayerStats stats = null!; + [field: Required] Rigidbody2D rb = null!; - + Vector2 moveDirection; BaseState currentState = new ImmobileMovementState(); SafeZone? safeZone; bool lastJumpButton; + #region Unity Messages void Awake() => rb = GetComponent(); void Start() => currentState.EnterState(this); void Update() { + if (gameFlowManager.Paused) + return; + if (currentState.UpdateState(this) is {} newState) SwitchState(newState); } void FixedUpdate() { + if (gameFlowManager.Paused) + return; + if (currentState.FixedUpdateState(this) is {} newState) SwitchState(newState); } void OnDrawGizmos() => currentState.OnDrawGizmos(this); + #endregion + + #region Inputs + public void OnMove(InputAction.CallbackContext ctx) { moveDirection = ctx.ReadValue(); if (moveDirection.sqrMagnitude > 1.0f) @@ -46,7 +61,7 @@ public class PlayerMovement : MonoBehaviour { if (!wasJustPressed) return; - + if (safeZone == null) return; @@ -57,11 +72,9 @@ public class PlayerMovement : MonoBehaviour { SwitchState(new EnterSafeZoneMovementState(safeZone)); } - void SwitchState(BaseState newState) { - currentState.LeaveState(this); - currentState = newState; - newState.EnterState(this); - } + #endregion + + #region Rigidbody void OnTriggerEnter2D(Collider2D other) { if (other.GetComponent() is {} triggeredSafeZone) @@ -85,6 +98,16 @@ public class PlayerMovement : MonoBehaviour { rb.isKinematic = !enabled; } + #endregion + + #region States + + void SwitchState(BaseState newState) { + currentState.LeaveState(this); + currentState = newState; + newState.EnterState(this); + } + class BaseState { public virtual void EnterState(PlayerMovement playerMovement) {} @@ -93,14 +116,14 @@ public class PlayerMovement : MonoBehaviour { public virtual BaseState? UpdateState(PlayerMovement playerMovement) => null; public virtual BaseState? FixedUpdateState(PlayerMovement playerMovement) => null; - + public virtual void OnDrawGizmos(PlayerMovement playerMovement) {} } class NormalMovementState : BaseState { public override BaseState? FixedUpdateState(PlayerMovement playerMovement) { playerMovement.rb.velocity = (Vector3)playerMovement.moveDirection * playerMovement.stats.movementSpeed; - + return null; } } @@ -126,7 +149,7 @@ public class PlayerMovement : MonoBehaviour { float currentTime = Time.time - startTime; if (currentTime >= duration) return Transition(); - + playerMovement.rb.MovePosition(Vector3.Lerp( startPosition, target, @@ -142,17 +165,18 @@ public class PlayerMovement : MonoBehaviour { class EnterSafeZoneMovementState : JumpingMovementState { readonly SafeZone safeZone; + public EnterSafeZoneMovementState(SafeZone safeZone) : base(safeZone.Stats.JumpDuration, safeZone.transform.position) { this.safeZone = safeZone; } public override void EnterState(PlayerMovement playerMovement) { base.EnterState(playerMovement); - + safeZone.EnterSafeZone(); playerMovement.SetRigidbodyEnabled(false); } - + protected override BaseState Transition() => new ImmobileMovementState(); protected override float ModifyLerpTime(float t) => safeZone.Stats.JumpSpeedCurve.Evaluate(t); @@ -160,13 +184,14 @@ public class PlayerMovement : MonoBehaviour { class ExitSafeZoneMovementState : JumpingMovementState { readonly SafeZone safeZone; + public ExitSafeZoneMovementState(SafeZone safeZone, Vector2 direction) : base(safeZone.Stats.JumpDuration, safeZone.GetOutsidePosition(direction)) { this.safeZone = safeZone; } public override void LeaveState(PlayerMovement playerMovement) { base.EnterState(playerMovement); - + safeZone.ExitSafeZone(); playerMovement.SetRigidbodyEnabled(true); } @@ -177,7 +202,7 @@ public class PlayerMovement : MonoBehaviour { class ImmobileMovementState : BaseState { public override void EnterState(PlayerMovement playerMovement) { base.EnterState(playerMovement); - + if (!playerMovement.rb.isKinematic) Debug.LogWarning("Rigidbody should probably be kinematic when immobile (when in safe zone)."); } @@ -197,4 +222,6 @@ public class PlayerMovement : MonoBehaviour { } #endif } + + #endregion } \ No newline at end of file