适用于多种NPC类型的C#FSM
作者:互联网
好的,这将是我需要帮助的一些代码.
前言
下面的代码现在描述了FSM的实现,因为我正在使用统一性,这使我可以根据自己的状态/动作和决策来创建资产.
状态
[CreateAssetMenu(menuName = "PluggableAI/States")]
public class State : ScriptableObject
{
public Action[] actions;
public Transition[] transitions;
public Color sceneGizmoColor = Color.grey;
public EnumProfession Profession;
/// <summary>
/// Updates current state
/// </summary>
/// <param name="controller"></param>
public void UpdateState(StateController controller)
{
DoActions(controller);
CheckTransitions(controller);
}
/// <summary>
/// Does each action
/// </summary>
/// <param name="controller"></param>
private void DoActions(StateController controller)
{
for (int i = 0; i < actions.Length; i++)
{
actions[i].Act(controller);
}
}
/// <summary>
/// Check which transition we have to ggo in
/// </summary>
/// <param name="controller"></param>
private void CheckTransitions(StateController controller)
{
for (int i = 0; i < transitions.Length; i++)
{
bool decisionSucceeded = transitions[i].decision.Decide(controller);
if (decisionSucceeded)
{
controller.TransitionToState(transitions[i].trueState);
}
else
{
controller.TransitionToState(transitions[i].falseState);
}
}
}
}
行动
public abstract class Action : ScriptableObject
{
public abstract void Act(StateController controller);
}
决断
public abstract class Decision : ScriptableObject
{
public abstract bool Decide (StateController controller);
}
过渡
public class Transition
{
public Decision decision;
public State trueState;
public State falseState;
}
为了控制状态及其转换,我创建了以下类StateController:
public class StateController : MonoBehaviour
{
public State CurrentState;
public State RemainState;
public NpcHuman NpcHuman;
/// <summary>
/// When the game starts
/// </summary>
private void Awake()
{
if (NpcHuman == null)
{
NpcHuman = GetComponent<NpcHuman>();
}
}
/// <summary>
/// Updates every frame
/// </summary>
void Update()
{
CurrentState.UpdateState(this);
}
/// <summary>
/// Transitions to next state
/// </summary>
/// <param name="nextState"></param>
public void TransitionToState(State nextState)
{
if (nextState != RemainState)
{
CurrentState = nextState;
onExitState();
}
}
/// <summary>
/// Is Called everytime a state exits
/// </summary>
private void onExitState()
{
}
public void ForceChangeState(State state)
{
CurrentState = state;
}
}
现在我所做的就是我已经根据自己的类型确定了我在游戏中拥有的不同类型的AI:
NPC的类型
Villager - Humanoid
Soldier - Humanoid
Archer - Humanoid
Catapult (vehicles) - Generic
Spirits - Generic
Animals - Generic
现在让我们从人形角色开始,我创建了以下关系:
现在,您可以看到每个类人动物类都是从类NpcHumanoid中派生的-图表中我的命名有误对不起
如果您一直在密切注意,您将已经发现此代码存在问题.
我现在的主要问题是对不同类型对象的引用.
所以我的问题是做到这一点的最佳方法是什么?
我应该为状态机创建一个抽象类,然后为该状态机创建一个子类,然后该子类可以保存对其控制的AI / NPC类型的引用.那将如何与我的州一起工作?看到它们都将StateController作为参数,我将不得不不断地将statecontroller强制转换为使用状态的类型(看起来像是粗俗的意大利面条)
另外,可能有一种解决方案,我看不到我希望获得你们的投入.
解决方法:
Unity使用基于组件的方法来组织游戏逻辑.因此,我认为最好的方法是对您的NPC类型使用组件而不是常规的OOP方法.
只需将不同类型的NPC视为具有不同组件的GameObject.例如,
村民
class Villager: MonoBehaviour
{
public float Fatigue;
public int Carrying;
}
您可以创建一个NPCFactory来创建不同的NPC.
class NPCFactory
{
public GameObject CreateNPC(NPCType npcType)
{
GameObject obj = new GameObject();
obj.AddComponent<StateController>();
switch(npcType)
{
case NPCType.Villager:
obj.AddComponent<Villager>();
break;
//case ....
}
return obj;
}
}
然后,您可以通过操纵它们上的StateController来处理NPC的状态.
标签:state-machine,artificial-intelligence,unity3d,c 来源: https://codeday.me/bug/20191109/2012539.html