Unity 状态模式(实例详解)

文章目录

      • 简介
      • 示例1:基础角色状态切换
      • 示例2:添加更多角色状态
      • 示例3:战斗状态
      • 示例4:动画同步状态
      • 示例5:状态机管理器
      • 示例6:状态间转换的条件触发
      • 示例7:多态行为与上下文类

简介

Unity 中的状态模式(State Pattern)是一种行为设计模式,它允许一个对象在其内部状态改变时改变其行为。在游戏开发中,状态模式常用于实现角色的不同行为状态切换,例如玩家角色的行走、奔跑、跳跃、攻击等不同状态。下面将通过五个简化示例来阐述如何在Unity中实现状态模式:

示例1:基础角色状态切换

// 定义抽象状态类
public abstract class CharacterState
{protected Character character;public void SetCharacter(Character _character){this.character = _character;}// 抽象方法,子类需要实现具体行为public abstract void Update();
}// 具体状态类:IdleState
public class IdleState : CharacterState
{public override void Update(){Debug.Log("角色处于闲置状态");// 检查是否应该转换到其他状态,如按下移动键则切换至MoveStateif (Input.GetKey(KeyCode.W)){character.ChangeState(new MoveState());}}
}// 具体状态类:MoveState
public class MoveState : CharacterState
{public override void Update(){Debug.Log("角色正在移动");// 检查是否应返回闲置状态或切换至其他状态if (!Input.GetKey(KeyCode.W)){character.ChangeState(new IdleState());}}
}// 角色类持有当前状态并处理状态切换
public class Character : MonoBehaviour
{private CharacterState currentState;public void ChangeState(CharacterState newState){if (currentState != null){currentState.SetCharacter(null);}currentState = newState;currentState.SetCharacter(this);}void Update(){currentState.Update();}
}

示例2:添加更多角色状态

public class JumpState : CharacterState
{public override void Update(){Debug.Log("角色正在跳跃");// 跳跃动作完成后切换回Idle或Move状态if (IsJumpFinished()){character.ChangeState(currentlyOnGround ? new IdleState() : new MoveState());}}
}// 初始化时设置初始状态
void Start()
{currentState = new IdleState();currentState.SetCharacter(this);
}

示例3:战斗状态

public class CombatState : CharacterState
{// 实现战斗相关的更新逻辑,比如检测敌人、攻击等public override void Update(){Debug.Log("角色处于战斗状态");// 检查战斗是否结束,结束后切换回Idle或Run状态if (CombatIsOver()){character.ChangeState(new IdleState());}}
}

示例4:动画同步状态

public class AnimationState : CharacterState
{Animator anim;public AnimationState(Character character, Animator animator){SetCharacter(character);anim = animator;}public override void Update(){// 根据当前状态播放相应的动画switch (GetType().Name){case nameof(IdleState):anim.Play("Idle");break;case nameof(MoveState):anim.Play("Run");break;// 其他状态对应的动画...}}
}

示例5:状态机管理器

// 为了更复杂的系统,可以创建一个专门管理状态切换和维护状态栈的类
public class StateMachine
{Stack<CharacterState> stateStack = new Stack<CharacterState>();public void PushState(CharacterState newState){stateStack.Push(newState);newState.SetCharacter(character);}public void PopState(){if (stateStack.Count > 0){var oldState = stateStack.Pop();oldState.SetCharacter(null);if (stateStack.Count > 0){currentState = stateStack.Peek();currentState.SetCharacter(character);}}}// 更新调用当前栈顶状态的方法public void Update(){currentState?.Update();}
}

以上代码仅作示例,并未涵盖所有异常处理和实际项目中的细节,但足以说明如何在Unity中应用状态模式来组织和管理不同角色状态的切换。

示例6:状态间转换的条件触发

在某些情况下,角色的状态切换可能需要基于特定的游戏事件或条件。下面展示一个基于冷却时间(Cooldown)的状态切换示例:

public class AttackState : CharacterState
{private float attackCoolDown;private bool canAttack;public AttackState(float coolDownTime){attackCoolDown = coolDownTime;canAttack = true;}public override void Update(){if (canAttack && Input.GetKeyDown(KeyCode.Space)){Debug.Log("角色进行攻击");// 触发攻击动作OnAttack();canAttack = false;Invoke(nameof(ResetAttack), attackCoolDown);}}private void ResetAttack(){canAttack = true;// 攻击结束后根据情况切换至其他状态,例如Idlecharacter.ChangeState(new IdleState());}private void OnAttack(){// 实际执行攻击逻辑,如播放动画、计算伤害等}
}

示例7:多态行为与上下文类

为了进一步解耦状态和角色实体,可以创建一个抽象的上下文类(Context),由它来持有当前状态并处理状态之间的切换:

// 抽象上下文类
public abstract class CharacterContext
{protected CharacterState currentState;public virtual void ChangeState(CharacterState newState){currentState?.Exit();currentState = newState;currentState.Enter(this);}public abstract void Update();// 状态进入和退出时调用的方法public virtual void NotifyStateEnter() => currentState.Enter(this);public virtual void NotifyStateExit() => currentState.Exit();
}// 具体上下文类:游戏角色实体
public class Player : CharacterContext
{// 其他游戏相关属性...public override void Update(){currentState.Update();}// 重写以添加额外的进入/退出通知逻辑public override void NotifyStateEnter() { ... }public override void NotifyStateExit() { ... }
}// 每个状态类实现Enter和Exit方法
public class WalkState : CharacterState
{public override void Enter(CharacterContext context){// 进入行走状态时的行为,比如启动行走动画}public override void Exit(){// 退出行走状态时的行为,比如停止行走动画}
}

以上示例展示了如何通过状态模式在Unity中灵活管理角色的不同状态,并允许状态之间根据特定条件和事件平滑切换。每个具体状态类都负责自己的行为逻辑,而上下文类则统一管理这些状态的切换。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/656776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法题】79. 单词搜索

题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或…

el-input 显示最大长度和已输入内容长度

效果如下图 多行文本框&#xff1a; 单行文本框&#xff1a; 需要设置 maxlength 和 show-word-limit 两个属性&#xff0c;在使用 maxlength 属性限制最大输入长度的同时&#xff0c;可通过设置 show-word-limit 属性来展示字数统计。 <el-inputtype"textarea&quo…

《HTML 简易速速上手小册》第6章:HTML 语义与结构(2024 最新版)

文章目录 6.1 语义化标签的重要性6.1.1 基础知识6.1.2 案例 1&#xff1a;使用 <article>, <section>, <aside>, <header>, 和 <footer>6.1.3 案例 2&#xff1a;构建带有嵌套语义化标签的新闻网站6.1.4 案例 3&#xff1a;创建一个带有 <mai…

SSD寻址单元IU对寿命的影响有多大?

随着存储技术的不断进步&#xff0c;固态硬盘SSD的容量正以惊人的速度增长&#xff0c;尤其是采用高密度QLC NAND闪存技术的大容量SSD&#xff0c;如30TB及以上级别的产品。QLC NAND由于每个单元能够存储4比特数据&#xff0c;从而显著提高了存储密度&#xff0c;但同时也带来了…

纯html+css+js静态汽车商城

首页代码 <!DOCTYPE html> <html class"no-js" lang"zxx"><head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&qu…

学会用Python分割、合并字符串

在很多情况下&#xff0c;我们需要对字符串进行分割或合并&#xff0c;以满足特定的需求&#xff0c;例如将字符串拆分成多个部分、将多个字符串合并成一个等等。Python提供了多种方法来进行字符串的分割和合并&#xff0c;本文将介绍其中几种常用的方法。 一、使用split()函数…

Vue-43、Vue中组件自定义事件

1、给学生绑定atguigu事件 2、在组件内触发事件 第二种写法 传多个参数。 解绑 解绑一个事件 解绑多个自定义事件 this.$off([xxx1,xxx2]);解绑所有事件 this.$off();总结

IDEA Java常用快捷键

目录 main方法快捷键&#xff1a;psvm输出语句&#xff1a;sout复制行&#xff1a;ctrld删除行&#xff1a;ctrly单行注释或多行注释 &#xff1a; Ctrl / 或 Ctrl Shift /for循环 直接 &#xff1a;fori代码块包围&#xff1a;try-catch,if,while等 ctrlaltt缩进&#xff1…

MBA十日读--经营经济学章节 笔记

第7天 经营 解决问题的方法大都取决于调动雇员的积极性 对每一个分解后的工作做进一步研究&#xff0c;可以找到完成它的最有效途径。如果将这些最有效的关键因素结合在一起&#xff0c;就能找到效率最高的生产方法 泰勒本人认为&#xf…

四、防御保护---防火墙NAT篇

四、防御保护---防火墙NAT篇 一、源NAT二、目标NAT三、双向NAT四、多出口NAT 一、源NAT 源NAT — 基于源IP地址进行转换。我们之前接触过的静态NAT&#xff0c;动态NAT&#xff0c;NAPT都属于源NAT&#xff0c;都是针对源IP地址进行转换的。源NAT主要目的是为了保证内网用户可…

SpringBoot-基础

SpringBoot-基础 1.IOC控制反转 Spring的核心是IoC&#xff08;Inversion of Control&#xff0c;控制反转&#xff09;容器&#xff0c;它可以管理容器内的普通Java对象以及对象之间关系的绑定&#xff08;Dependency Injection依赖注入&#xff09;。容器中被管理的对象称为…

基于Javassist字节码增强实现本地公参传递

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 背景 测试线上的公参是通过skywalking agent的方式进行传递的。 如果是本地则会因为获取不到公参报错影响正常测试。所以需要本地也进行公参传递 正常链路是 前…

一体化设计:兼容多种OS系统Linux网关楼宇DDC

在工业物联网&#xff08;IIoT&#xff09;和智能建筑领域&#xff0c;钡铼网关具备高度灵活性与强大计算能力的边缘网关产品正逐渐成为推动行业智能化转型的关键要素。本文将详细介绍的基于Linux系统的4G工业智能网关&#xff0c;不仅拥有NXP i.MX8M Mini四核64位处理器的强大…

设计一个数据库连接池

注意点 限制连接池中最多可以容纳的连接数目&#xff0c;避免过度消耗系统资源当客户请求连接&#xff0c;而连接池中所有连接都已被占用时&#xff0c;一种方式是让客户一直等待&#xff0c;直到有空闲连接&#xff0c;另一种方式是为客户分配一个新的临时连接。当客户不在使…

《golang设计模式》第三部分·行为型模式-10-模板方法(Template Method)

文章目录 1. 概述1.1 角色1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 类图 1. 概述 模板方法&#xff08;Template Method&#xff09;用来定义算法的框架&#xff0c;将算法中的可变步骤定义为抽象方法&#xff0c;指定子类实现或重写。 1.1 角色 AbstractClass&#xff08;…

质数判断(5种方法)

1.普通枚举所有因数 if(n<2) return 0; if(n2) return 1; for(int i2;i<n/2;i) if(!(n%i)) return 0; return 1; 2.枚举所有因数对中较小的部分&#xff08;到sqrt(n)&#xff09; if(n<2) return 0; if(n2) return 1; int tmpsqrt(n)//注意&#xff0c;n为大整数时…

Kettle-Docker部署+Sqlserver数据同步Mysql+Start定时任务

一. 背景介绍 1. ETL是什么 ETL&#xff08;Extract-Transform-Load&#xff09;&#xff0c;即数据抽取、转换、装载的过程。它是一种思想&#xff0c;主要是说&#xff0c;从不同的数据源获取数据&#xff0c;并通过对数据进行处理&#xff08;格式&#xff0c;协议等转换&a…

Java-12a.Spring 中通过 TaskDecorator 配置默认异步线程池

Java-12.Spring 中通过 ThreadPoolTaskExecutor 和 AsyncConfigurerSupport 配置默认异步线程池 前言 在Spring框架中&#xff0c;TaskDecorator 是一个接口&#xff0c;它可以用来自定义由 ThreadPoolTaskExecutor 或其他任务执行器管理的任务的装饰行为。这通常用于在执行任…

第32关 k8s集群管理开源神器 - k9s

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维。 随着我们管理维护的K8S集群上线&#xff0c;怎么管理好集群上面成百上千的服务pod&#xff0c;就是我们该操心的事情了。这里博哥把在生产中一直在用的一个开源管理工具k8s&#xff0c;github…

Jenkins如何从GIT下拉项目并启动Tomcat

一、先添加服务器 二、添加视图 点击控制台输出&#xff0c;滑到最下面&#xff0c;出现这个就说明构建成功了&#xff0c;如果没有出现&#xff0c;说明构建有问题&#xff0c;需要解决好问题才能启动哦~