当前位置: 首页 > news >正文

杭州劳保网站制作网站备案查询系统

杭州劳保网站制作,网站备案查询系统,一般做网站宽度是多少,运行怎么打开wordpress目录 1、状态模式 2、使用工具 3、状态模式适用范围 4、实现内容 5、代码及思路 Enemy.cs EnemyState.cs 6、unity里的设置 7、运行效果展示 1、状态模式 “允许一个对象在其内部状态改变时改变自身的行为。对象看起来好像是在修改自身类。” 就是一个对象能随着自己…

目录

1、状态模式

2、使用工具

3、状态模式适用范围

4、实现内容

5、代码及思路 

Enemy.cs

EnemyState.cs

6、unity里的设置

7、运行效果展示


1、状态模式

“允许一个对象在其内部状态改变时改变自身的行为。对象看起来好像是在修改自身类。”

就是一个对象能随着自己的状态改变执行不同的方法吧,而这个方法和状态并不是写在这个对象类里的,却能达到像是对象修改自身类的效果。

2、使用工具

Unity2022.3.51f1c1、visual studio code

3、状态模式适用范围

1)你有一个游戏实体,它的行为基于它的内部状态改变

2)这些状态被严格分为相对数目较少的小集合

3)游戏实体随着时间的变化会响应用户输入或一些游戏事件

在游戏里广泛使用在ai里,也经常被应用于用户输入处理、浏览菜单屏幕、解析文件、网络协议和其他异步的行为

4、实现内容

实现敌人能在这几个状态之间根据距离远近自动切换,hp为0时死亡

三段距离:一段距离内攻击,一段距离内追逐,更远的距离会暂停

但是暂停、防御的触发、检验技能是否释放完毕等功能并没有实现,这里只是搭框架,原理都差不多,只要学会一个条件的状态转移其他的都很好做,就不赘述了。

5、代码及思路 

书上的代码看着太复杂了,写的时候没有完全参考,我更倾向于围绕状态模式的目标——将每个状态相关的所有数据和行为封装对应状态类里面 来写。

状态模式的基本模式:参考状态模式 | 菜鸟教程

  • 上下文类(Enemy):它持有一个状态引用,并在状态改变时更新行为
  • 状态类(EnemyState):定义所有可能的状态并为它们提供行为接口
  • 具体状态类(IdleState\StandState...):实现状态接口的具体类,表示对象的某一具体状态

具体来说在我的代码里结构是这样的

Enemy.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
// 每个敌人身上都该有
public class Enemy : MonoBehaviour
{[HideInInspector]public EnemyState state;public int distance;// 距离public int thresholdA=10;// 阈值Apublic int thresholdB=20;// 阈值Bpublic int hp=10;// 血量UnityEvent<Enemy> stateChangeEvent = new UnityEvent<Enemy>();//状态改变事件void Start(){ChangeState(EnemyState.IdleState);//设置为初始状态}public void ChangeState(EnemyState newState){if (state != null){stateChangeEvent.RemoveListener(state.handleData);//移除原本的方法引用}state = newState;//切换至新状态stateChangeEvent.AddListener(state.handleData);//添加新状态的方法引用stateChangeEvent.Invoke(this);//调用下一个状态的handleData}}
  • 在Start方法中初始化了敌人的状态并调用初始状态的handleData方法,这样在开始时,敌人就会执行与IdleState状态相关的行为。
  • 当敌人的状态改变时,ChangeState方法通过 stateChangeEvent.Invoke(this)触发事件,从而调用切换后状态的 handleData方法。(有一个坑是在使用AddListener的时候里面的参数传的其实是一个方法引用(地址值),因此在改变state的值以前,一定要把原本注册的方法移除,再添加新的,不然调用的还会是之前状态的方法/空引用异常。)

这本书这部分写得真不咋滴啊,对象类的函数不清不楚,没写如果把条件判断也加到状态类里去了,对象要怎么切换状态,这部分是我自己想的。

EnemyState.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using Unity.VisualScripting.Antlr3.Runtime;
using UnityEditor;
using UnityEditor.EditorTools;
using UnityEngine;public class EnemyState :MonoBehaviour
{// 定义所有可能的状态public static IdleState IdleState; // 空闲状态public static StandState StandState; // 站立状态public static MoveState MoveState; // 移动状态public static AttackState AttackState; // 攻击状态public static DieState DieState; // 死亡状态public static DefenseState DefenseState;// 防御状态void Awake(){// Awake方法在对象被激活时调用且会被派生类继承// 派生类生成时也会被调用,所以一定要加条件防止重复添加if (gameObject.GetComponent<IdleState>() == null){// 添加各个状态的组件实例// 用add的原因是继承自MonoBehaviour的类不能直接newIdleState = gameObject.AddComponent<IdleState>();StandState = gameObject.AddComponent<StandState>();MoveState = gameObject.AddComponent<MoveState>();AttackState = gameObject.AddComponent<AttackState>();DieState = gameObject.AddComponent<DieState>();DefenseState = gameObject.AddComponent<DefenseState>();}}// 虚拟的handleData方法,用于每个状态具体的处理逻辑public virtual void HandleData(Enemy enemy){// 检查敌人的血量StartCoroutine(UpdateDieState(enemy));}// 虚拟的状态更新方法,每个状态可以自定义自己的更新逻辑public virtual IEnumerator UpdateState(Enemy enemy){yield return null;}// 死亡状态的更新方法,持续检查敌人的血量是否小于等于零public  IEnumerator UpdateDieState(Enemy enemy)//这个只需要在初始状态调一次{while (true){if (enemy.hp <= 0){enemy.ChangeState(EnemyState.DieState);break;}yield return null;}}}
public class IdleState :EnemyState
{public override void HandleData(Enemy enemy){base.HandleData(enemy);// 调用基类的处理方法,检查死亡状态Debug.Log("初始状态");enemy.ChangeState(EnemyState.StandState);}
}
public class StandState : EnemyState
{public override void HandleData(Enemy enemy){Debug.Log("站立状态");StartCoroutine(UpdateState(enemy));// 开始更新状态,判断是否切换到其他状态}public override IEnumerator UpdateState(Enemy enemy){while (true){if (enemy.distance < enemy.thresholdA) // 距离小于阈值A,进入攻击状态{enemy.ChangeState(EnemyState.AttackState);yield break; // 结束当前协程}else if (enemy.distance > enemy.thresholdA) // 距离大于阈值A,进入移动状态{enemy.ChangeState(EnemyState.MoveState);yield break; // 结束当前协程}yield return null; // 每帧检查一次}}
}
public class MoveState : EnemyState
{public override void HandleData(Enemy enemy){Debug.Log("追逐状态");StartCoroutine(UpdateState(enemy)); // 开始更新状态,判断是否切换到其他状态}public override IEnumerator UpdateState(Enemy enemy){while (true){if (enemy.distance < enemy.thresholdA) // 距离小于阈值A,进入站立状态{enemy.ChangeState(EnemyState.StandState);break; // 结束当前协程}yield return null; // 每帧检查一次}}}
public class AttackState : EnemyState
{public override void HandleData(Enemy enemy){Debug.Log("攻击状态");StartCoroutine(UpdateState(enemy));// 开始更新状态,判断是否切换到其他状态}public override IEnumerator UpdateState(Enemy enemy){while (true){if (enemy.distance > enemy.thresholdA) // 距离大于阈值A,进入移动状态{enemy.ChangeState(EnemyState.MoveState);break; // 结束当前协程}yield return null; // 每帧检查一次}}
}
public class DieState : EnemyState
{public override void HandleData(Enemy enemy){GameObject.Destroy(enemy.gameObject);// 销毁敌人对象,表示死亡Debug.Log("死亡状态");}
}
public class DefenseState : EnemyState
{public override void HandleData(Enemy enemy){Debug.Log("防御状态");StartCoroutine(UpdateState(enemy));// 开始更新状态,判断是否切换到其他状态}public override IEnumerator UpdateState(Enemy enemy){while (true){//如果是释放过程中注意都要等防御技能结束才行//防御状态要切换到其他状态的条件应是被打断/成功防住if (enemy.distance > enemy.thresholdA)// 距离大于阈值A,进入移动状态{enemy.ChangeState(EnemyState.MoveState);break;// 结束当前协程}else if (enemy.distance < enemy.thresholdA)// 距离小于阈值A,进入攻击状态{enemy.ChangeState(EnemyState.AttackState);break;// 结束当前协程}yield return null;// 每帧检查一次}}
}
  • 通过EnemyState 作为基类来定义所有可能的敌人状态(如 IdleState、MoveState、AttackState 等)。每个状态类都会实现 handleData方法和 UpdateState 协程方法,这样每个状态都可以自定义自己的行为和状态转移条件。
  • 状态切换:通过 enemy.ChangeState(EnemyState.XXX) 来切换敌人的状态,每个状态都有自己的逻辑来判断何时切换到下一个状态。
  • 血量和死亡判断:EnemyState类中的 UpdateDieState 协程用于实时检查敌人的血量,一旦血量降至 0 或以下,就会触发死亡状态并销毁敌人对象。
  • 状态更新:handleData 方法负责初始化和启动状态检查,UpdateState 协程负责检查条件并更新状态。
6、unity里的设置

建一个空物体挂上EnemyState类(继承自monobehavior类的都需要挂到某物体上才能用)

建两个胶囊体挂上Enemy类,阈值和血量可以根据敌人的不同自定义,这里我随便设的值。

7、运行效果展示

由于这只是框架,所以我检查效果的方式就是直接在Inspector里调Distance来观察状态转换是否成功。对照着这个状态转移图来看:

运行后,两个胶囊体分别从初始进入站立状态,又由于d<a而进入攻击状态

将其中一个胶囊体的Distance调为11>a,攻击->追逐。另外可观察到另一个胶囊体状态不受影响

将胶囊体Distance调回0,按照状态转移图从追逐->站立->攻击

最后,将胶囊体的Hp调为0 ,该胶囊体切换至死亡状态后执行销毁行为,另一胶囊体不受影响。

http://www.khdw.cn/news/50104.html

相关文章:

  • 广州建设高端网站活动推广朋友圈文案
  • 深圳画册设计公司哪家好手机优化是什么意思
  • 怎么用单位电脑做网站服务器百度seo怎么优化
  • 渝北网站建设微信公众号软文怎么写
  • 网络服务提供者利用网络侵害他人厦门seo搜索排名
  • wordpress流水布局主题公司seo是指什么意思
  • 微网站费用哈尔滨百度推广联系人
  • 住建局查询系统快速排名优化seo
  • 装修公司网站开发福建网络seo关键词优化教程
  • 响应式网站模仿今日新闻消息
  • 网站可以做弹窗广告么seo网站首页推广
  • 曲阜做网站的公司某网站搜索引擎优化
  • 那个网站做车险分期长沙网络推广
  • 网站留言功能网站为什么要seo
  • 潍坊网站建设公司哪家好做关键词优化
  • 手机端网站做app网站seo优化分析
  • 网页打不开qq能上厦门谷歌seo公司
  • 数据型网站建设网页设计与制作书籍
  • 注册网站域名的入口杭州百度seo代理
  • 网站是做百度快照推广好淘宝运营主要做些什么
  • 做技术分享网站有哪些厦门人才网官网招聘
  • 网站首页不见怎么做东莞推广公司
  • 重庆公司做网站百度公司官网首页
  • 给人做违法网站规避湖北短视频seo营销
  • 成都网站设计优选柚v米科技seo网络营销推广
  • 网络综合设计实验报告seo和网络推广有什么区别
  • 个人网站的设计与实现西安seo招聘
  • les做ml网站企业推广平台有哪些
  • 电子商务网站建设与维护读书心得引流软件下载站
  • 做教育集团的网站建设关键词优化价格表