unity 一个简单的有限状态机

      快几个月没写博客了,今天不知道是那根神经接错了。今天来跟大家讲一下一个比较简单实用的有限状态机。有限状态机看起来名字高大上似得,其实就是一堆if else,如果没有有限状态机的话我们就直接这样写了,

using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour {

	public enum BehaviourType
	{
	    None,
        Idle,
        Attack,
        Run,
        Walk,
        BeAttack,
        Death
	}

    private BehaviourType _currentType;
	private void Start () 
    {
	    _currentType=BehaviourType.None;
	}
	private void Update () 
    {
	    switch (_currentType)
	    {
            case BehaviourType.Attack:
                ActionAttack();
                break;
            case BehaviourType.Idle:
                ActionIdle();
                break;
            case BehaviourType.Walk:
                ActionWalk();
                break;
            case BehaviourType.Run:
                ActionRun();
                break;
            case BehaviourType.BeAttack:
                ActionBeAttack();
                break;
            case BehaviourType.Death:
                ActionDeath();
                break;
	    }
	}

    private void ActionIdle()
    {
        Debug.Log("Idle");
    }
    private void ActionRun()
    {
        Debug.Log("Run");
    }
    private void ActionWalk()
    {
        Debug.Log("Walk");
    }
    private void ActionAttack()
    {
        Debug.Log("Attack");
    }
    private void ActionBeAttack()
    {
        Debug.Log("BeAttack");
    }
    private void ActionDeath()
    {
        Debug.Log("Death");
    }
}
如果只有一个玩家 或者npc存在这样的行为,假如npc是这样的行为,玩家的行为比这个还要复杂,那么我们是不是在每个存在不同行为的行为类中去写一个switch或者if else语句呢?并且这样还容易出错,很容易讲他们之间的行为写乱了。如果一个玩家行为类中只有一个执行行为的方法,而这些switch语句都放到一个类中去管理,或者说我们不用switch语句,直接到一个状态的时候直接调用一个方法。switch语句耦合性太高了,如果我们能写成如下这样的话那么可以大大的降低耦合性了。
    private void Update () 
    {
        //switch (_currentType)
        //{
        //    case BehaviourType.Attack:
        //        ActionAttack();
        //        break;
        //    case BehaviourType.Idle:
        //        ActionIdle();
        //        break;
        //    case BehaviourType.Walk:
        //        ActionWalk();
        //        break;
        //    case BehaviourType.Run:
        //        ActionRun();
        //        break;
        //    case BehaviourType.BeAttack:
        //        ActionBeAttack();
        //        break;
        //    case BehaviourType.Death:
        //        ActionDeath();
        //        break;
        //}
	    if (情况1)
	    {
                ChangeState(BehaviourType.Attack);
	    }
       
	}
如果在情况1的条件下 我们就自动执行了ActionAttack方法的话,这样我们的代码会更加简洁,这样我们不用去改一个Switch语句里面的case了,我们只需在指定的情况下切换到某个状态即可,然后写一个通用类去管理他的方法它的调用关系就行了,问题的关键是怎么写好这样一个类,这个类肯定需要和当前行为类存在一定的关系,行为类中写一些列的行为方法,而这样一个通用类就会执行该行为类的方法。当然一个笨的方法就只将该行为类的引用赋值给这个通用类,如果我们赋值了,那怎么让它什么情况执行什么方法呢?难道我们在该通用类中这样写:

public  class TestStateMachine:MonoBehaviour
{
    public NewBehaviourScript Behaviour;

    public TestStateMachine(NewBehaviourScript s)
    {
        Behaviour = s;
    }

    private void Update()
    {
        switch (hideFlags)
        {
                
        }
    }
}
卧槽 如果这样写和直接放到行为类中有什么区别啊,那不是脱裤子放屁,其实不是,其实这样写的好处你把一些简单的方法和一个复杂的逻辑分开了一样似得,就好比一个把一个类的数据和方法分开一样,我们用的是的只需将方法和数据结合就可以轻松搞定了,同样也便于我们阅读代码和后期修改bug。这个通用类应该是保存行为类中的一个保存
BehaviourType和对应方法的指针。然后我们最后用一个类管理所有包含行为类状态变化的类,这样我们就需要了解一个基本的c#特性和反射的知识。今天就写到这里了,后面花2到3节的时间讲讲具体怎么弄。如果有什么问题可以私聊我,本人的qq号:1850761495.




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值