IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 【Godot】状态机设计和使用方式 -> 正文阅读

[游戏开发]【Godot】状态机设计和使用方式

Godot 3.4.2

下面是一个简单的有限状态机基类,之后是一个使用状态机的思路

State.gd

#============================================================
#	State
#============================================================
#  子状态
#============================================================
# @datetime: 2022-3-15 17:03:14
#============================================================

class_name State
extends Node


onready var state_machine = get_parent()


#============================================================
#   Set/Get
#============================================================
func get_state_machine():
	return state_machine

func get_current_state() -> State:
	return state_machine.get_current_state() as State

func get_blackboard():
	return get_state_machine().get_blackboard() as StateBlackboard



#============================================================
#   自定义
#============================================================
## 进入到这个状态时
func enter(data):
	pass

## 退出这个状态时
func exit():
	pass

## 执行到当前状态时,会切换为调用这个方法
func state_process(delta):
	pass

## 切换状态
func switch_to(state, data: Dictionary = {}):
	state_machine.switch_to(state, data)


StateMachine.gd

#============================================================
#	State Machine
#============================================================
#  状态机
#============================================================
# @datetime: 2022-3-15 17:02:55
#============================================================

class_name StateMachine
extends Node


signal state_changed(last_state, current_state)


var current_state
var current_state_node : State
var blackboard : StateBlackboard setget , get_blackboard
var states := {}



#============================================================
#   Set/Get
#============================================================
func get_state_node_list() -> Array:
	return states.values()

func get_blackboard():
	if blackboard == null:
		for child in get_children():
			if child is StateBlackboard:
				blackboard = child
	return blackboard

func get_state_node(state) -> State:
	return states[state] as State



#============================================================
#   内置
#============================================================
func _ready():
	# 找到所有子状态机
	for child in get_children():
		if child is State:
			# 根据节点的 name 作为 key 添加状态
			states[child.name] = child
			#child.set_physics_process(false)
			#child.set_process(false)
	
	if states.size() > 0:
		# 第一个节点
		current_state = states.keys()[0]
		current_state_node = get_state_node(current_state)
		current_state_node.enter(null)
	else:
		set_physics_process(false)
		printerr("没有添加状态节点,状态机没有启动")


func _physics_process(delta):
	current_state_node.state_process(delta)



#============================================================
#   自定义
#============================================================
func switch_to(state, data: Dictionary = {}):
	if state != current_state:
		current_state_node.exit()
		emit_signal("state_changed", current_state, state)
		# 切换到当前
		current_state = state
		current_state_node = get_state_node(current_state)
		current_state_node.enter(data)

Blackboard.gd(存储状态机的全局数据)

#============================================================
#	Blackboard
#============================================================
#  状态黑板
#============================================================
# @datetime: 2022-3-15 17:31:58
#============================================================

class_name StateBlackboard
extends Node


var data : Dictionary = {}


func _enter_tree():
	# 状态机根节点的 blackboard 属性为自身
	get_parent().blackboard = self



在做的时候,我会创建对应类型的状态机、状态和对应的黑板

比如我要给 Player 节点设计状态机,我会先创建对应的 PlayerStateMachine(Player状态机)、PlayerState(Player状态基类)、PlayerBlackboard(Player状态机黑板)

这个设计之后,我们开始添加如下节点结构

  • PlayerStateMachine
    • PlayerBlackboard
    • 多个 PlayerState

在这里插入图片描述
如上图所示,IdleMoveJump 等都是继承自 PlayerState,这些状态在某些功能需求上是相同的,比如在 IdleMoveJumpFall 都可以接收输入进行移动,在 PlayerState 里我们需要对这些功能进行编写。(注意这些都是共用的功能,如果是共用一个数据,一般都写在 Blackboard 里)。

比如下面几个功能

Idle 状态里
在这里插入图片描述
Move 状态
在这里插入图片描述
Jump 状态
在这里插入图片描述
PlayerState 中,Player 可以执行的能力。
在这里插入图片描述
input 开头的方法是指可以执行的功能, 接收 移动 攀爬 跳跃 落下 等等行为,每个行为都会返回一个 布尔值 bool,用以判断是否执行了这个功能。

如果功能是可以执行多个的,比如 input_move() 可以在移动的时候执行其他功能,则直接不在 if 里进行优先级判断,而在 if 中的,则会有一个优先级,只能执行其中的一个动作,不能同时执行,因为总不能说,在跳跃的时候又同时在爬楼梯。

把功能都写在这个类型的基础状态类里,全局的数据写在 Blackboard 节点里。

按照这样的设计与逻辑编写,状态机里添加状态节点,这样,我们的一个状态机就完成了。

在这里插入图片描述

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:31:30  更:2022-03-17 22:31:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 16:59:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码