Unity3D优化技巧系列八

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

下面给读者讲解在游戏开发中经常使用的FSM有限状态机的实现,有限状态机在状态切换中使用的非常多,比如足球游戏,动作游戏等。角色在游戏场景中经常需要动作的切换,比如Idle,Run,Attack,Skill等,这些技能状态之间的切换,我们通常会使用FSM去处理。我们在游戏中将动作切换和技能切换放在一起使用FSM处理,下面通过代码的方式给读者进行封装处理:

	public interface EntityFSM
	{
		bool CanNotStateChange{set;get;}
		FsmState State { get; }
		void Enter(Ientity entity , float stateLast);
		bool StateChange(Ientity entity , EntityFSM state);
		void Execute(Ientity entity);
		void Exit(Ientity Ientity);
	}

先定义一个抽象类用于具体状态的实现,游戏中的具体状态,我们通过枚举的方式定义如下:

	public enum FsmState
	{
		FSM_STATE_FREE,
		FSM_STATE_RUN,
       		 FSM_STATE_SING,
		FSM_STATE_RELEASE,
        	FSM_STATE_LEADING,
        	FSM_STATE_LASTING,
		FSM_STATE_DEAD,
       	 	FSM_STATE_ADMOVE,
        	FSM_STATE_FORCEMOVE,
        	FSM_STATE_RELIVE,
        	FSM_STATE_IDLE,
	}

下面告诉大家如何使用我们具体的动作状态切换,具体实现就是继承上面定义的接口:

 public class EntityIdleFSM : EntityFSM
	{
        public static readonly EntityFSM Instance = new EntityIdleFSM();

		public FsmState State
		{
			get
            		{
               		 	return FsmState.FSM_STATE_IDLE;
			}
		}

		public bool CanNotStateChange{
			set;get;
		}

		public bool StateChange(Ientity entity , EntityFSM fsm)
        	{
			return CanNotStateChange;
		}

		public void Enter(Ientity entity , float last)
        	{
            		entity.OnEnterIdle();
		}

		public void Execute(Ientity entity)
        	{
            		if (EntityStrategyHelper.IsTick(entity, 3.0f))
           	 	{
                		entity.OnFSMStateChange(EntityFreeFSM.Instance);
            		}
		}

		public void Exit(Ientity entity){

		}
	}

在这个函数中使用了一个接口Ientity,其实它主要实现的是状态之间的切换,下面就把该类的主要功能实现如下所示:

 /// <summary>
        /// 状态改变
        /// </summary>
        /// <param name="fsm"></param>
        /// <param name="last"></param>
        public void OnFSMStateChange(EntityFSM fsm, float last)
        {
            if (this.FSM != null && this.FSM.StateChange(this, fsm))
            {
                return;
            }

            if (this.FSM == fsm && this.FSM != null && this.FSM.State == FsmState.FSM_STATE_DEAD)
            {
                return;
            }
            if (this.FSM != null)
            {
                this.FSM.Exit(this);
            }

            if (this.FSM != null)
                this.RealEntity.FSMStateName = fsm.ToString();

            this.FSM = fsm;
            StrategyTick = Time.time;
            this.FSM.Enter(this, last);
        }

        public void OnFSMStateChange(EntityFSM fsm)
        {
            if (this.FSM != null && this.FSM.StateChange(this, fsm))
            {
                return;
            }

            if (this.FSM == fsm && this.FSM != null && (this.FSM.State == FsmState.FSM_STATE_DEAD))
            {
                return;
            }

            if (this.FSM != null)
            {
                this.FSM.Exit(this);
            }

            this.FSM = fsm;
            if (this.FSM != null)
                this.RealEntity.FSMStateName = fsm.ToString();
            StrategyTick = Time.time;
            this.FSM.Enter(this, 0.0f);
        }

该类还提供了各个动作的接口,实现如下所示:

	public virtual void OnEnterIdle()
        {
            this.RealEntity.PlayerAnimation("idle");
        }

        /// <summary>
        /// Run状态进入时调用
        /// </summary>
        public virtual void OnEnterMove()
        {
        }

这个RealEntity类实现的是具体的动作或者是新动画触发函数封装事例代码如下所示:

	public void PlayerIdleAnimation()
    	{
        	if (this.animation == null)
        	{
           	 	return;
       		 }

        PlayerAnimation("idle");
        this.animation.PlayQueued("free");
    }

	public void PlayerFreeAnimation()
    {
        if (this.animation == null)
        {
            return;
        }

        PlayerAnimation("free");
	}

	public void PlayerRunAnimation(){
		if (this.animation == null) {
			return;
		}
        PlayerAnimation("walk");
	}

技能的接口实现跟这个类似,代码如下所示:

	public class EntityReleaseSkillFSM : EntityFSM
	{
		public static readonly EntityFSM Instance = new EntityReleaseSkillFSM();
		public FsmState State{
			get
			{
				return FsmState.FSM_STATE_RELEASE;
			}
		}
		public bool CanNotStateChange{
			set;get;
		}

		public bool StateChange(Ientity entity , EntityFSM fsm){
			return CanNotStateChange;
		}

		public void Enter(Ientity entity , float last){
			//Debug.LogError("prepareplayskill enter!");
			entity.OnEntityReleaseSkill();
		}

		public void Execute(Ientity entity){
            //entity.OnEntityPrepareAttack ();
		}

		public void Exit(Ientity entity){

		}
	}

这样我们的FSM状态机就实现完成了,使用该框架开发了多款游戏,效果如下:

时间: 2024-10-07 05:31:22

Unity3D优化技巧系列八的相关文章

Unity3D优化技巧系列五

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 架构设计也是优化的一种,一款游戏如果没有一个好的架构,程序出现问题很难做到及时的响应,读者可以试想一下,如果编程的时候只是为了实现功能而实现功能,到头来就是代码越写越乱,各种功能交织

Unity3D优化技巧系列七

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144. 上篇博客实现了LoginState的封装,其实作为UI的各个窗口,每个窗口都对应着自己的State也就是状态类.这么多状态类,不能鼓孤立的存在着,它也需要我们封装一个状态管理类去处

Unity3D脚本中文系列教程(八)

◆ static var matrix : Matrix4x4 描述:设置用于渲染所有gizmos的矩阵. 类方法 ◆ Static function DrawCube(center:Vector3,size:Vector3):void 描述:用center和size绘制一个立方体.function OnDrawGizmosSelected() {        //在变换位置处绘制一个变透明的蓝色立方体        Gizmos.color=Color(1,0,0,5);        Gi

零基础unity3d游戏开发系列目录

零基础Unity3D游戏开发系列 第一章:游戏开发与游戏引擎(一) 零基础Unity3D游戏开发系列 第一章:游戏开发与游戏引擎(二) 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)界面... 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)创建与打开项目I 零基础unity3d游戏开发系列 第二章:unity3d概览(一)创建与打开项目II 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)创建与打开项目III 零基础Unity3D游戏开发

让数据库飞起来 十大DB2优化技巧

DB2是IBM出口的一系列关系型数据库管理系统,分别在不同的操作系统平台上服务.下文中将为大家讲解DB2十大优化技巧. 为了帮助DB2 DBA 避免性能灾难并获得高性能,我为我们的客户.用户和 DB2 专家同行总结了一套故障诊断流程.以下详细说明在 Unix.Windows 和 OS/2 环境下使用 DB2 UDB 的电子商务OLTP 应用程序的10 条最重要的性能改善技巧,希望下文中涉及到的内容对大家能够有所帮助. 一. 监视开关 确保已经打开监视开关.如果它们没有打开,您将无法获取您需要的性

SQL优化技巧(Oracle)

SQL优化技巧(1): Where子句中的连接顺序:oracle采用自下而 上的顺序解析where子句,根据这个原理,表 之间的连接必须写在其他where条件之前,那些可以过滤掉大量记录的条件 必须写在where子句的末尾. 例如 低效:select * from report_sale_account e where hsje>5000 and dzxl = '000001' and 25<(select count(*) from report_sale_account where cod

S5PV210开发系列八_Yaffs的移植

S5PV210开发系列八 Yaffs的移植 象棋小子    1048272975 Nand作为市面上最基本的非易失性闪存技术之中的一个,应用在各种固态大容量存储解决方式中.因为Nand flash自身的特点,Nand存储器往往须要一款专用的Nand文件系统进行管理.开源的Yaffs文件系统因为其优异的性能,在Nand flash中受到广泛的应用,笔者此处就Yaffs的移植作一个简单的介绍. 1. Yaffs概述 Yaffs是由Aleph One公司所发展出来的Nand flash文件系统,专门为

10个CSS简写/优化技巧

CSS简写就是指将多行的CSS属性简写成一行,又称为CSS代码优化或CSS缩写. CSS简写的最大好处就是能够显著减少CSS文件的大小,优化网站整体性能,更加容易阅读. 下面介绍常见的CSS简写规则: 一.盒子大小 这里主要用于两个属性:margin和padding,我们以margin为例,padding与之相同. 盒子有上下左右四个方向,每个方向都有个外边距: margin-top:1px; margin-right:2px; margin-bottom:3px; margin-left:4p

MyEclipse 2015优化技巧(整合)

MyEclipse 2015优化技巧(整合) MyEclipse 2015优化速度方案仍然主要有这么几个方面:去除无需加载的模块.取消冗余的配置.去除不必要的检查.关闭更新. 第一步: 去除不需要加载的模块 一个系统20%的功能往往能够满足80%的需求,MyEclipse也不例外,我们在大多数时候只需要20%的系统功能,所以可以将一些不使用的模块禁止加载启动.通过Windows- Preferences打开配置窗口,依次选择左侧的General--> Startup and Shutdown,这