我在Unity中编写游戏,其中一个游戏具有不同的游戏模式,但最终使用相同的级别,只是事情表现不同。
区别仅在于玩家如何瞄准目标,因此他/她必须快速找到目标的相同位置(目标以相同的顺序出现)或者它们随机出现。
它是相同的阶段,但有不同的规则,所以我认为 firebase.database().ref('myRef').child('myChild').set({
name: newUser.displayName,
username: newUser.username,
email: newUser.email
})
将是有益的 - GameManager 类基于游戏模式实现它。当然,我可以编写不同的游戏管理器或在一个中使用interface
,但我希望保持组织有变化。
问题是,怎么做?
答案 0 :(得分:2)
这是您设置简单状态机的方法:
//state
public enum GameMode { Normal, Endless, Campaign, Idle, Count }
private GameMode gameMode;
//state machine array
private delegate void UpdateDelegate();
private UpdateDelegate[] UpdateDelegates;
void Awake()
{
//setup all UpdateDelegates here to avoid runtime memory allocation
UpdateDelegates = new UpdateDelegate[(int)GameMode.Count];
//and then each UpdateDelegate
UpdateDelegates[(int)GameMode.Normal] = UpdateNormalState;
UpdateDelegates[(int)GameMode.Endless] = UpdateEndlessState;
UpdateDelegates[(int)GameMode.Campaign] = UpdateCampaignState;
UpdateDelegates[(int)GameMode.Idle] = UpdateIdleState
gameMode = GameMode.Idle;
}
void Update()
{
//call the update method of current state
if(UpdateDelegates[(int)gameMode]!=null)
UpdateDelegates[(int)gameMode]();
}
现在你可以分开每个州的逻辑:
void UpdateNormalState() {
//...
//write logic for normal state
}
//...
//same for other states
这样当你改变gameMode时,新状态的更新方法将在当前帧结束后被迭代调用。
了解更多信息,watch this video
关于状态机的好处是它们易于处理(与switch-case或许多ifs相比)。你有一系列的方法,可以用它们做任何你想做的事情,但仍然确保它们中只有一个可以一次运行。更改状态的最大延迟始终与Time.deltaTime一样短(如果使用Update方法调用状态机方法)
您甚至可以制作状态机2D。但请确保分配所有UpdateDelegates
public enum GameMode { Normal, Endless, Campaign, Idle, Count }
public enum GameState { Playing, Paused, GameOver, Idle, Count }
private UpdateDelegate[,] UpdateDelegates;
UpdateDelegates = new UpdateDelegate[(int)GameMode.Count, (int)GameState.Count];
如果您的游戏不够,您可以使用高级状态机。这是我从某个地方复制过的示例代码,尚未经过测试:
此方法使用状态之间的转换。例如使用给定的MoveNext
调用Command
,并根据状态机的当前ProcessState
和给定的命令将状态更改为下一个ProcessState
。
using System;
using System.Collections.Generic;
namespace Juliet
{
public enum ProcessState
{
Inactive,
Active,
Paused,
Terminated
}
public enum Command
{
Begin,
End,
Pause,
Resume,
Exit
}
public class Process
{
class StateTransition
{
readonly ProcessState CurrentState;
readonly Command Command;
public StateTransition(ProcessState currentState, Command command)
{
CurrentState = currentState;
Command = command;
}
public override int GetHashCode()
{
return 17 + 31 * CurrentState.GetHashCode() + 31 * Command.GetHashCode();
}
public override bool Equals(object obj)
{
StateTransition other = obj as StateTransition;
return other != null && this.CurrentState == other.CurrentState && this.Command == other.Command;
}
}
Dictionary<StateTransition, ProcessState> transitions;
public ProcessState CurrentState { get; private set; }
public Process()
{
CurrentState = ProcessState.Inactive;
transitions = new Dictionary<StateTransition, ProcessState>
{
{ new StateTransition(ProcessState.Inactive, Command.Exit), ProcessState.Terminated },
{ new StateTransition(ProcessState.Inactive, Command.Begin), ProcessState.Active },
{ new StateTransition(ProcessState.Active, Command.End), ProcessState.Inactive },
{ new StateTransition(ProcessState.Active, Command.Pause), ProcessState.Paused },
{ new StateTransition(ProcessState.Paused, Command.End), ProcessState.Inactive },
{ new StateTransition(ProcessState.Paused, Command.Resume), ProcessState.Active }
};
}
public ProcessState GetNext(Command command)
{
StateTransition transition = new StateTransition(CurrentState, command);
ProcessState nextState;
if (!transitions.TryGetValue(transition, out nextState))
throw new Exception("Invalid transition: " + CurrentState + " -> " + command);
return nextState;
}
public ProcessState MoveNext(Command command)
{
CurrentState = GetNext(command);
return CurrentState;
}
}
public class Program
{
static void Main(string[] args)
{
Process p = new Process();
Console.WriteLine("Current State = " + p.CurrentState);
Console.WriteLine("Command.Begin: Current State = " + p.MoveNext(Command.Begin));
Console.WriteLine("Command.Pause: Current State = " + p.MoveNext(Command.Pause));
Console.WriteLine("Command.End: Current State = " + p.MoveNext(Command.End));
Console.WriteLine("Command.Exit: Current State = " + p.MoveNext(Command.Exit));
Console.ReadLine();
}
}
}