Unity 状态模式(实例详解)

news2024/9/22 11:30:26

文章目录

      • 简介
      • 示例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("角色处于闲置状态");
        // 检查是否应该转换到其他状态,如按下移动键则切换至MoveState
        if (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;
        // 攻击结束后根据情况切换至其他状态,例如Idle
        character.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.coloradmin.cn/o/1421505.html

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

相关文章

一个产品是怎么诞生的

一个产品的诞生&#xff0c;首先从假设需求开始&#xff0c;或者从玩耍的创客开始。 假设需求往往风险很大&#xff0c;你如果没有结合实际的生活经验或者是玩耍经验&#xff0c;凭空在脑子里想到一个东西&#xff0c;要把它创造出来&#xff0c;这样的东西极有可能会遭遇商业上…

ASP.NET Core 使用 SignalR 的简单示例

写在前面 ASP.NET SignalR 是一个开源代码库&#xff0c;简化了Web实时通讯方案&#xff0c;可以实时地通过服务端将信息同步推送到各个客户端&#xff0c;可应用于 需要从服务器进行高频更新的应用&#xff1a;包括游戏、社交网络、投票、拍卖、地图和GPS应用&#xff1b; 仪…

Servlet过滤器个监听器

过滤器和监听器 过滤器 什么是过滤器 当浏览器向服务器发送请求的时候&#xff0c;过滤器可以将请求拦截下来&#xff0c;完成一些特殊的功能&#xff0c;比如&#xff1a;编码设置、权限校验、日志记录等。 过滤器执行流程 Filter实例 package com.by.servlet;import jav…

2024年航海制造工程与海洋工程国际会议(ICNMEME2024)

一、【会议简介】 2024年航海制造工程与海洋工程国际会议(ICNMEME2024)旨在将研究人员、工程师、科学家和行业专业人士聚集在一个开放论坛上&#xff0c;展示他们在导航制造工程与海洋工程领域的激励研究和知识转移理念。然而&#xff0c;我们也认识到&#xff0c;工程师的未来…

【操作系统·考研】虚拟内存管理

1.概述 传统存储管理方式具有两个特征 一次性&#xff1a;作业必须一次性全部装入内存后&#xff0c;才能开始运行。驻留性&#xff1a;作业被装入内存后&#xff0c;就一直驻留在内存中&#xff0c;在其运行期间作业的任何部分都无法被换出。 显然&#xff0c;这两个特性非…

【深度学习】数据归一化/标准化 Normalization/Standardization

目录 一、实际问题 二、归一化 Normalization 三、归一化的类型 1. Min-max normalization (Rescaling) 2. Mean normalization 3.Z-score normalization (Standardization) 4.非线性归一化 4-1 对数归一化 4-2 反正切函数归一化 4-3 小数定标标准化&#xff08;Demi…

山海鲸智慧教育方案:教育数据的未来

作为山海鲸可视化软件的开发者&#xff0c;我们深知数据可视化在教育领域的重要价值。山海鲸智慧教育解决方案正是在这样的背景下应运而生&#xff0c;致力于为教育行业提供高效、直观的数据可视化解决方案。 随着教育信息化的深入推进&#xff0c;教育数据呈爆炸式增长。如何…

嵌入式学习 Day14

一. 三个函数 1.strncpy char *strncpy(char *dest, const char *src, size_t n) // 比正常拷贝多了一个n { n < strlen(src) // 只拷贝前n个字符&#xff0c;最终dest中不会有\0 n strlen(src) // 正常拷贝 n > strlen(src) …

【Golang】ModbusRTU协议CRC16校验算法

CRC校验码是通过在数据后面附加一个短的校验序列来生成的&#xff0c;用于检测数据在传输过程中是否发生错误。CRC16是一种特定的CRC校验算法&#xff0c;它生成一个16位的校验码。 下面是使用Go语言实现CRC16校验算法的代码&#xff1a; package main import ("encoding…

【01】Linux 基本操作指令

带⭐的为重要指令 &#x1f308; 01、ls 展示当前目录下所有文件&#x1f308; 02、pwd 显示用户当前所在路径&#x1f308; 03、cd 进入指定目录&#x1f308; 04、touch 新建文件&#x1f308; 05、tree 以树形结构展示所有文件⭐ 06、mkdir 新建目录⭐ 07、rmdir 删除目录⭐…

某赛通电子文档安全管理系统 PolicyAjax SQL注入漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

Linux--redhat9创建软件仓库

1.插入光盘&#xff0c;挂载镜像 模拟插入光盘: 点击:虚拟机-可移动设备-CD/DVD 设备状态全选&#xff0c;使用ISO影响文件选择当前版本镜像&#xff0c;点击确认。 2.输入: df -h 可以显示&#xff0c;默认/dev/sr0文件为光盘文件&#xff0c;挂载点为/run/media/root/镜像…

【操作系统·考研】文件系统基础

1.概述 文件(File)是以硬盘为载体的存储在计算机上的信息集合&#xff0c;文件可以是文本文档、图片、程序等&#xff0c;基本访问单元可以是字节或记录&#xff0c;可以长期储存在硬盘中&#xff0c;并允许可控制的进程间共享访问&#xff0c;还可以被组成成更复杂的结构。 在…

关于 IntelliJ IDEA 中 Schedule for Addition 的问题

IntelliJ IDEA是一款强大的Java集成开发环境&#xff0c;由JetBrAIns公司开发。它以其智能代码编辑、代码分析工具、自动代码补全、强大的调试功能和内建的版本控制等特性而闻名。此外&#xff0c;它还支持Kotlin、Groovy、Scala和Android开发等多种语言和框架。 IntelliJ IDE…

【XR806开发板试用】在 xr806 上用 ncnn 跑神经网络 mnist

在 xr806 上用 ncnn 跑神经网络 mnist 0x0 介绍 xr806 和 ncnn https://xr806.docs.aw-ol.com/ XR806是全志科技旗下子公司广州芯之联研发设计的一款支持WiFi和BLE的高集成度无线MCU芯片&#xff0c;支持鸿蒙L0系统 https://github.com/Tencent/ncnn ncnn是腾讯开源的高性…

纯静态微信小程序水果商城

首页代码 <view class"container"><!-- 轮播图 --><view class"swiper-container"><swiper class"screen-swiper" indicator-dots"true" circular"true" autoplay"true" interval"300…

【开源】基于JAVA+Vue+SpringBoot的数据可视化的智慧河南大屏

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 A4.2 数据模块 B4.3 数据模块 C4.4 数据模块 D4.5 数据模块 E 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的数据可视化的智慧河南大屏&#xff0c;包含了GDP、…

Unity:构建游戏和交互应用的强大引擎

Unity&#xff1a;构建游戏和交互应用的强大引擎 在游戏开发和交互应用领域&#xff0c;Unity 已经成为最受欢迎和广泛使用的开发引擎之一。无论是独立开发者、游戏工作室还是企业开发团队&#xff0c;Unity 都提供了强大的工具和功能&#xff0c;帮助开发者构建出令人惊叹的视…

【Prometheus】Prometheus的容器化部署

目录 实验部署 1、创建账户绑定集群 2、node-exporter发现节点 3、创建configmap&#xff0c;传输配置文件&#xff1a; 3.1、热更新修改configmap方式&#xff1a; 4、部署Prometheus&#xff1a; 5、部署service提供外部访问&#xff1a; 6、安装grafana可视化工具&am…

win wsl2 Ubuntu-22.04 设置时间为国内时间

使用 wsl2 安装 Ubuntu-22.04 后 时间不正确&#xff0c;主要有两个原因 时区设置不正确&#xff0c;国内为京八区。 时区正确后&#xff0c;没有同步时间。&#xff08;大部分人容易忽略这一点&#xff09; Linux 默认情况下使用 UTC 格式作为标准时间格式&#xff0c;如果在…