1
1
using System ;
2
- using System . Collections ;
3
- using System . Collections . Generic ;
4
- using System . Linq ;
5
2
using Core . Common ;
6
- #if UNITY_EDITOR
7
- using UnityEditor ;
8
- #endif
9
3
using UnityEngine ;
10
4
11
5
namespace Core . Game
12
6
{
13
- public enum GameState
14
- {
15
- //happens only once when game is first loaded on start
16
- //used to load assets and initialize GameManager
17
- Initializing ,
18
- //when loading between scenes or game states
19
- //from landing to play from game scene to menu...
20
- Loading ,
21
- //first landing scene (main menu)
22
- Landing ,
23
- //in game scene/playing game
24
- Play ,
25
- //when game is paused - still in game scene
26
- Pause ,
27
- //when game is over (Player is dead) - still in game scene
28
- GameOver ,
29
- //onApplicationQuit (maybe use for dispose/garbage collection)
30
- Quitting
31
- }
32
-
33
7
//run before everything else
34
8
[ DefaultExecutionOrder ( - 1 ) ]
35
9
public class GameManager : Singleton < GameManager >
@@ -54,13 +28,25 @@ private void InvokeReady()
54
28
IsReady = true ;
55
29
}
56
30
31
+ // Add new GameStates here.
32
+ private IGameState [ ] AllStates => new IGameState [ ] {
33
+ new Loading ( ) ,
34
+ new Landing ( ) ,
35
+ new Play ( ) ,
36
+ new Pause ( ) ,
37
+ new GameOver ( ) ,
38
+ new Quitting ( )
39
+ } ;
40
+
41
+ private int _currentStateIndex = - 1 ;
42
+
57
43
[ field: SceneList ] [ field: SerializeField ] public int LandingScene { get ; private set ; }
58
44
59
45
[ field: SceneList ] [ field: SerializeField ] public int GameScene { get ; private set ; }
60
46
61
- public GameState State { get ; private set ; } = GameState . Initializing ;
47
+ public IGameState CurrentState => _currentStateIndex < 0 ? null : AllStates [ _currentStateIndex ] ;
62
48
63
- public bool InGame => State == GameState . Play || State == GameState . Pause || State == GameState . GameOver ;
49
+ public bool InGame => CurrentState is IInGameState ;
64
50
65
51
private void Start ( )
66
52
{
@@ -71,175 +57,167 @@ private void Initialize()
71
57
{
72
58
//all other managers are already initialized OnEnable
73
59
InvokeReady ( ) ;
60
+
61
+ // use for loop since states are mostly structs.
62
+ for ( int i = 0 ; i < AllStates . Length ; i ++ )
63
+ {
64
+ AllStates [ i ] . Initialize ( ) ;
65
+ }
74
66
75
67
//now it has finished initializing change state to loading - loading landing scene
76
- ChangeGameState ( GameState . Loading ) ;
68
+ ChangeGameState < Loading > ( ) ;
77
69
78
70
//load first/landing scene
79
- Common . Utils . LoadScene ( LandingScene , delegate { ChangeGameState ( GameState . Landing ) ; } ) ;
71
+ Utils . LoadScene ( LandingScene , ChangeGameState < Landing > ) ;
80
72
}
81
73
82
- private void ChangeGameState ( GameState newState )
74
+ private void ChangeGameState < T > ( ) where T : IGameState
83
75
{
84
- if ( newState == State )
76
+ if ( ! AllStates . FindIndex ( s => s is T , out int index ) )
77
+ {
78
+ Debug . LogError ( $ "{ nameof ( IGameState ) } of type { typeof ( T ) . Name } not found.") ;
79
+
80
+ return ;
81
+ }
82
+
83
+ if ( _currentStateIndex == index )
84
+ {
85
+ Debug . LogWarning ( $ "{ nameof ( IGameState ) } already { CurrentState } .") ;
86
+
87
+ return ;
88
+ }
89
+
90
+ IGameState newState = AllStates [ index ] ;
91
+
92
+ if ( ! newState . IsReady )
85
93
{
86
- Debug . LogWarning ( $ "{ nameof ( GameState ) } already { State } ") ;
94
+ Debug . LogWarning ( $ "{ typeof ( T ) . Name } { nameof ( IGameState ) } is not ready. ") ;
87
95
88
96
return ;
89
97
}
90
98
91
- Debug . Log ( $ "{ nameof ( GameState ) } changed from { State } to { newState } ") ;
99
+ // Disable previous state.
100
+ if ( _currentStateIndex != - 1 )
101
+ {
102
+ AllStates [ _currentStateIndex ] . Disable ( ) ;
103
+ }
104
+
105
+ Debug . Log ( $ "{ nameof ( IGameState ) } changed from { CurrentState . TypeName ( ) } to { newState . TypeName ( ) } .") ;
106
+
107
+ _currentStateIndex = index ;
108
+
109
+ newState . Enable ( ) ;
110
+
111
+ // Update current state reference since states can be structs.
112
+ AllStates [ _currentStateIndex ] = newState ;
92
113
93
- State = newState ;
114
+ EventBus < GameStateEnabled < T > > . Invoke ( ) ;
94
115
95
- EventBus < GameStateChanged > . Invoke ( new GameStateChanged ( State ) ) ;
116
+ EventBus < GameStateChanged > . Invoke ( new GameStateChanged ( CurrentState ) ) ;
96
117
}
97
118
98
119
public void StartGame ( bool continued )
99
120
{
100
121
if ( continued )
101
122
{
102
- ContinueGame ( ) ;
123
+ LoadSavedGame ( ) ;
103
124
}
104
125
105
126
else
106
127
{
107
- StartNewGame ( ) ;
128
+ LoadNewGame ( ) ;
108
129
}
109
130
}
110
131
111
132
//load persistent data first
112
- private void ContinueGame ( bool reload = false )
133
+ private void LoadSavedGame ( bool tryAgain = false )
113
134
{
114
135
//change to loading until scene loads async
115
- ChangeGameState ( GameState . Loading ) ;
136
+ ChangeGameState < Loading > ( ) ;
116
137
117
- Debug . Log ( "Loading Game..." ) ;
138
+ Debug . Log ( "Loading Saved Game..." ) ;
118
139
119
140
//load game scene and call onSceneLoaded
120
- Common . Utils . LoadScene ( GameScene , NewGameStarted , reload ) ;
141
+ Utils . LoadScene ( GameScene , GameStarted , tryAgain ) ;
121
142
}
122
143
123
- private void StartNewGame ( )
144
+ private void LoadNewGame ( )
124
145
{
125
146
//change to loading until scene loads async
126
- ChangeGameState ( GameState . Loading ) ;
147
+ ChangeGameState < Loading > ( ) ;
127
148
128
149
Debug . Log ( "Loading New Game..." ) ;
129
150
130
151
//load game scene and call onSceneLoaded
131
- Common . Utils . LoadScene ( GameScene , NewGameStarted ) ;
152
+ Utils . LoadScene ( GameScene , GameStarted ) ;
132
153
}
133
154
134
155
//when game scene finished loading
135
- void NewGameStarted ( )
156
+ void GameStarted ( )
136
157
{
137
- ChangeGameState ( GameState . Play ) ;
158
+ ChangeGameState < Play > ( ) ;
138
159
139
160
Debug . Log ( "Loaded New Game" ) ;
140
161
}
141
162
142
163
public void ExitGame ( )
143
164
{
144
- #if UNITY_EDITOR
145
- EditorApplication . isPlaying = false ;
146
- #else
147
- Application . Quit ( ) ;
148
- #endif
165
+ ChangeGameState < Quitting > ( ) ;
149
166
}
150
167
151
168
//leave/unload game scene and load to Landing scene
152
169
public void ExitToMainMenu ( )
153
- {
154
- if ( InGame )
155
- {
156
- //change to loading until scene loads async
157
- ChangeGameState ( GameState . Loading ) ;
158
-
159
- Debug . Log ( $ "exiting { nameof ( GameScene ) } ...") ;
160
-
161
- //load landing scene and call onSceneLoaded
162
- Common . Utils . LoadScene ( LandingScene , GameExited ) ;
163
- }
164
-
165
- else
166
- {
167
- Debug . LogError ( $ "can't exit { nameof ( GameScene ) } when { nameof ( GameState ) } is not an { nameof ( InGame ) } { State } ") ;
168
- }
169
- }
170
-
171
- public void TryAgain ( )
172
170
{
173
171
if ( ! InGame )
174
172
{
175
- Debug . LogError ( "Can 't Not in Game .") ;
173
+ Debug . LogError ( $ "can 't exit when { nameof ( CurrentState ) } is not an { nameof ( IInGameState ) } .") ;
176
174
177
175
return ;
178
176
}
179
177
180
- GameExited ( ) ;
178
+ //change to loading until scene loads async
179
+ ChangeGameState < Loading > ( ) ;
181
180
182
- ContinueGame ( true ) ;
181
+ Debug . Log ( $ "exiting { nameof ( GameScene ) } ...") ;
182
+
183
+ //load landing scene and call onSceneLoaded
184
+ Utils . LoadScene ( LandingScene , GameExited ) ;
185
+ }
186
+
187
+ public void TryAgain ( )
188
+ {
189
+ LoadSavedGame ( true ) ;
183
190
}
184
191
185
192
//called once landing scene is loaded
186
193
private void GameExited ( )
187
194
{
188
- Debug . Log ( $ "Exited { nameof ( GameScene ) } ") ;
195
+ Debug . Log ( $ "Exited { nameof ( GameScene ) } . ") ;
189
196
190
- ChangeGameState ( GameState . Landing ) ;
191
-
192
- //reset timeScale in case it was exited in pause
193
- Time . timeScale = 1f ;
197
+ ChangeGameState < Landing > ( ) ;
194
198
}
195
199
196
200
public void PauseGame ( )
197
201
{
198
- //pause only from GameState.Play
199
- if ( State != GameState . Play )
200
- {
201
- Debug . LogWarning ( $ "can't { nameof ( PauseGame ) } when { nameof ( GameState ) } is { State } ") ;
202
-
203
- return ;
204
- }
205
-
206
- Time . timeScale = 0f ;
207
-
208
- ChangeGameState ( GameState . Pause ) ;
202
+ ChangeGameState < Pause > ( ) ;
209
203
}
210
204
211
205
public void GameOver ( )
212
206
{
213
- if ( ! InGame )
214
- {
215
- Debug . LogWarning ( $ "can't { nameof ( GameOver ) } when { nameof ( GameState ) } is { State } ") ;
216
-
217
- return ;
218
- }
219
-
220
- Time . timeScale = 0f ;
221
-
222
- ChangeGameState ( GameState . GameOver ) ;
207
+ ChangeGameState < GameOver > ( ) ;
223
208
}
224
209
225
210
public void ResumeGame ( )
226
211
{
227
- //resume only from GameState.Pause
228
- if ( State != GameState . Pause )
229
- {
230
- Debug . LogWarning ( $ "can't { nameof ( ResumeGame ) } when { nameof ( GameState ) } is { State } ") ;
231
-
232
- return ;
233
- }
234
-
235
- Time . timeScale = 1f ;
236
-
237
- ChangeGameState ( GameState . Play ) ;
212
+ ChangeGameState < Play > ( ) ;
238
213
}
239
214
240
215
private void OnApplicationQuit ( )
241
216
{
242
- ChangeGameState ( GameState . Quitting ) ;
217
+ if ( ! ( CurrentState is Quitting ) )
218
+ {
219
+ ChangeGameState < Quitting > ( ) ;
220
+ }
243
221
}
244
222
}
245
223
}
0 commit comments