public interface IState { void OnEnter(params object[] parameters); void OnEnter(); void OnExit(); }
public interface IUIShowableHidable { void ShowUI(); void HideUI(); }
public abstract class UIState : IState { protected abstract IUIShowableHidable ShowableHidable { get; set; } protected abstract void Enter(params object[] parameters); protected abstract void Enter(); protected abstract void Exit(); public virtual void OnEnter() { ShowableHidable.ShowUI(); Enter(); } public virtual void OnExit() { ShowableHidable.HideUI(); Exit(); } public virtual void OnEnter(params object[] parameters) { ShowableHidable.ShowUI(); Enter(parameters); } }
public class UIShowableHidable : CachableMonoBehaviour, IUIShowableHidable { protected virtual void Awake() { gameObject.SetActive(false); } public virtual void ShowUI() { gameObject.SetActive(true); } public virtual void HideUI() { gameObject.SetActive(false); } protected bool TrySendAction(Action action) { if (action == null) return false; action(); return true; } }
public interface IMenuService { void GoToScreenOfType<T>() where T : UIState; void GoToScreenOfType<T>(params object[] parameters) where T : UIState; void GoToPreviousScreen(); void ClearUndoStack(); }
public class StateSwitcher { private IState currentState; private readonly List<IState> registeredStates; private readonly Stack<StateSwitchCommand> switchingHistory; private StateSwitchCommand previousStateSwitchCommand; public StateSwitcher() { registeredStates = new List<IState>(); switchingHistory = new Stack<StateSwitchCommand>(); } public void ClearUndoStack() { switchingHistory.Clear(); } public void AddState(IState state) { if (registeredStates.Contains(state)) return; registeredStates.Add(state); } public void GoToState<T>() { GoToState(typeof(T)); } public void GoToState<T>(params object[] parameters) { GoToState(typeof(T), parameters); } public void GoToState(Type type) { Type targetType = type; if (currentState != null) if (currentState.GetType() == targetType) return; foreach (var item in registeredStates) { if (item.GetType() != targetType) continue; if (currentState != null) currentState.OnExit(); currentState = item; currentState.OnEnter(); RegStateSwitching(targetType, null); } } public void GoToState(Type type, params object[] parameters) { Type targetType = type; if (currentState != null) if (currentState.GetType() == targetType) return; foreach (var item in registeredStates) { if (item.GetType() != targetType) continue; if (currentState != null) currentState.OnExit(); currentState = item; currentState.OnEnter(parameters); RegStateSwitching(targetType, parameters); } } public void GoToPreviousState() { if (switchingHistory.Count < 1) return; StateSwitchCommand destination = switchingHistory.Pop(); previousStateSwitchCommand = null; if (destination.parameters == null) { GoToState(destination.stateType); } else { GoToState(destination.stateType, destination.parameters); } } private void RegStateSwitching(Type type, params object[] parameters) { if (previousStateSwitchCommand != null) switchingHistory.Push(previousStateSwitchCommand); previousStateSwitchCommand = new StateSwitchCommand(type, parameters); } private class StateSwitchCommand { public StateSwitchCommand(Type type, params object[] parameters) { stateType = type; this.parameters = parameters; } public readonly Type stateType; public readonly object[] parameters; } }
public class MenuManager : IMenuService { private readonly StateSwitcher stateSwitcher; public MenuManager() { stateSwitcher = new StateSwitcher(); } public MenuManager(params UIState[] states) : this() { foreach (var item in states) { stateSwitcher.AddState(item); } } public void GoToScreenOfType<T>() where T : UIState { stateSwitcher.GoToState<T>(); } public void GoToScreenOfType(Type type) { stateSwitcher.GoToState(type); } public void GoToScreenOfType<T>(params object[] parameters) where T : UIState { stateSwitcher.GoToState<T>(parameters); } public void GoToScreenOfType(Type type, params object[] parameters) { stateSwitcher.GoToState(type, parameters); } public void GoToPreviousScreen() { stateSwitcher.GoToPreviousState(); } public void ClearUndoStack() { stateSwitcher.ClearUndoStack(); } }
public sealed class GameEndState : UIState { protected override IUIShowableHidable ShowableHidable { get; set; } private readonly GameEndUI gameEndUI; private Action onRestartButtonClicked; private Action onMainMenuButtonClicked; public GameEndState(IUIShowableHidable uiShowableHidable, GameEndUI gameEndUI) { ShowableHidable = uiShowableHidable; this.gameEndUI = gameEndUI; } protected override void Enter(params object[] parameters) { onRestartButtonClicked = (Action) parameters[0]; onMainMenuButtonClicked = (Action)parameters[1]; gameEndUI.onRestartButtonClicked += onRestartButtonClicked; gameEndUI.onMainMenuButtonClicked += onMainMenuButtonClicked; gameEndUI.SetGameEndResult((string)parameters[2]); gameEndUI.SetTimeText((string)parameters[3]); gameEndUI.SetScoreText((string)parameters[4]); } protected override void Enter() { } protected override void Exit() { gameEndUI.onRestartButtonClicked -= onRestartButtonClicked; gameEndUI.onMainMenuButtonClicked -= onMainMenuButtonClicked; } }
public class GameEndUI : UIShowableHidable { public static GameEndUI Instance { get; private set; } [SerializeField] private Text gameEndResultText; [SerializeField] private Text timeText; [SerializeField] private Text scoreText; [SerializeField] private Button restartButton; [SerializeField] private Button mainMenuButton; public Action onMainMenuButtonClicked; public Action onRestartButtonClicked; protected override void Awake() { base.Awake(); Instance = this; restartButton.onClick.AddListener(() => { if(onRestartButtonClicked != null) onRestartButtonClicked(); }); mainMenuButton.onClick.AddListener(() => { if (onMainMenuButtonClicked != null) onMainMenuButtonClicked(); }); } public void SetTimeText(string value) { timeText.text = value; } public void SetGameEndResult(string value) { gameEndResultText.text = value; } public void SetScoreText(string value) { scoreText.text = value; } }
private IMenuService menuService; private void InitMenuService() { menuService = new MenuManager ( new MainMenuState(MainMenuUI.Instance, MainMenuUI.Instance, playmodeService, scoreSystem), new SettingsState(SettingsUI.Instance, SettingsUI.Instance, gamePrefabs), new AboutAuthorsState(AboutAuthorsUI.Instance, AboutAuthorsUI.Instance), new GameEndState(GameEndUI.Instance, GameEndUI.Instance), playmodeState ); } ... private void OnGameEnded(GameEndEventArgs gameEndEventArgs) { Timer.StopTimer(); scoreSystem.ReportScore(score); PauseGame(!IsGamePaused()); Master.GetMenuService().GoToScreenOfType<GameEndState>( new Action(() => { ReloadGame(); PauseGame(false); }), new Action(() => { UnloadGame(); PauseGame(false); }), gameEndEventArgs.gameEndStatus.ToString(), Timer.GetTimeFormatted(), score.ToString()); }
Source: https://habr.com/ru/post/310236/
All Articles