全文基于 Godot 4.3 编写
GDScript 是一門 物件導向 的 指令式 程式設計語言
- 極快的編譯和載入速度
- 內建 Vector型矢量计算
- 與靜態型別相比效能較差
- 沒有 垃圾回收
- 引擎會預設進行引用計數,在大多數情況下為你管理記憶體
- 緩型別 。變數預設是動態型別
编辑器
界面
- 菜单中文:编辑器>设置>界面>编辑器>编辑器语言:zh_CN;设置本地化启用
- 属性中文:编辑器>设置>界面>检查器>默认属性名称样式:Localized
- 编辑器tab页:按照scene顺序习惯,切换到不同scene工作,及新建
快捷键
类型 | 功能 | WIN快捷键 |
目录树操作 | 创建新文件 | 编辑器: Ctrl+N |
节点操作 | 创建子节点 | 选中节点:Ctrl+A |
复制子节点 | 选中节点:Ctrl+C Ctrl+V | |
创建主场景 | Ctrl+N | |
编辑窗口 | 专注模式 | Ctrl+Shift+F11 |
关闭scene tab | Ctrl+Shift+W | |
关闭脚本文件 | Ctrl+W | |
双视图预览 | Ctrl+2 | |
打开2D编辑器 | Ctrl+F1 | |
打开3D编辑器 | Ctrl+F2 | |
打开Script编辑器 | Ctrl+F3 | |
打开AssetLib编辑器 | Ctrl+F4 | |
脚本编程 | 大写 | Shift+F4 |
小写 | Shift+F5 | |
删除行 | Ctrl+Shift+K | |
复制行 | Ctrl+ALT+Down | |
运行操作 | 控制台开关 | Ctrl+J |
run | F5 | |
run scene | F6 | |
pause | F7 | |
stop | F8 | |
set breakpoint | F9 | |
step_over | F10 | |
step_into | F11 | |
continue | F12 | |
设置
- 缩进自动处理:编辑器>文本>行为>缩进,每次ctrl+s会自动转换
插件
- 可视化逻辑: https://github.com/CraterCrash/godot-orchestrator 或者从编辑器的AssetLib里搜下载,需要VPN,放入addons目录
编程知识
场景(根节点)
- 创建场景:编辑窗口tab页的加号,点击创建,选择根节点的场景类型
- 创建关联脚本:选中场景tab时,点击场景栏过滤器右侧的脚本加号,作用域为所管辖的节点树
- 项目启动场景:项目设置>运行>选择一个场景文件
- 场景运行时:运行时,场景树会多出一行,可以查看remote的场景树,会实时更新包括怪物刷新时的场景树变化
节点(子节点)
- 新建子节点
- 场景栏:选中父节点,Ctrl+A
- 脚本:new节点实例,通过$定位一个已有节点,对它.add_child(new_instance)
- 定位节点
- get_tree()
- get_parent().get_node("Camera3D")
- get_viewport().get_camera_3d()
- $main_div/talent_box
- node_instance..get_children()
- 属性设置
- 检查器:属性设置
- button样式
- 创建样式:主题覆盖>样式:新建StyleBoxFlat>设置颜色阴影等
- 克隆样式:选中上述的样式,右键复制,再到别的按钮的主题覆盖的样式,右键粘贴
- 统一样式:样式右键存为文件,别的地方再加载文件
- textureRect样式
- png图片的强制大小:扩展模式改为Ignore size,自定义大小64*64即可
- button样式
- 脚本:$main_div/talent_box/talent_info/Label.text = talent["desc"]
- 检查器:属性设置
- 移除子节点
- 场景栏:选中子节点,delete
- 脚本:已有节点.remove_child(exist_instance)
信号
- 连接信号
- 检查器节点-选择信号-连接-关联方法
- 脚本
- button.connect("mouse_entered", _on_talent_button_entered)
- button.mouse_entered.connect(_on_talent_button_entered)
语法
- 基本信息
- 游戏窗口物理大小:get_viewport().get_visible_rect().size
- 获取相机镜头:get_viewport().get_camera_3d()
- 默认方法
- _ready方法:scene加载时,会触发gd的默认方法
- _process方法:场景逐帧自动触发的方法,此时空间为运动
- 鼠标屏幕坐标:get_viewport().get_mouse_position() mouse pos ray camera
- 窗口缩放比例:global_transform.basis.get_scale()
- 窗口实际分辨率:get_viewport().get_visible_rect().size
- _input _输入,期间空间锁定静态,如果此时检查碰撞,会插空
- _unhandled_input _未处理的_输入
- 字符串
- 字符串格式化:
"You collected %s coins" % [str(score)]
- 字符串格式化:
- 运算
- 随机值:randi() % n (0 ~ n-1之间取一个随机值,符合下标逻辑)
- 浮点相等:touch_target_position.is_equal_approx(position),相当于==
- 函数
- 默认参数值:foo(param: String = “default”) 并且有默认值的放后面
- 可变参数:foo(array or dict) 不支持*args 这样的形参
- 数据结构
- list
- 深拷贝:talent_exist_options.duplicate()
- 合并:talent_all_options.append_array(talent_add_options)
- 乱序:talent_add_options.shuffle()
- 裁剪:talent_add_options.resize(5),不足5个用null填充
- list
打包
windows
- 导出模板:编辑器>管理导出模板>从文件安装>选择tpz文件(https://godotengine.org/download/windows/ )
- 签名工具:编辑器设置>导出>windows>signtool选择osslsigncode.exe(https://github.com/mtrojnar/osslsigncode/releases )
- 图标工具:编辑器设置>导出>windows>rcedit选择rcedit-x64.exe( https://github.com/electron/rcedit )
- 导出选项
- 导出路径
- 代码签名,需要则启用
- 内嵌PCK,勾选则打包为单文件
android
- 安装开发工具
- JDK环境:下载解压JDK
- SDK环境:安装安卓studio
- SDK管理器获取SDK路径
- 勾选platform-tools、build-tools;34.0.0、platforms;android-34、cmdline-tools、cmake;3.10.2.4988404、ndk;23.2.8568313
- 签名文件:JDK的keytool生成
# 示例 keytool -keyalg(指定算法) RSA -genkeypair(生成密钥对) -alias(别名) androiddebugkey -keypass(别名密码) android -keystore(密钥文件名) debug.keystore -storepass(密钥密码) android -dname(证书拥有者) "CN=Android Debug,O=Android,C=US" -validity(有效期天) 9999 -deststoretype(目标密钥库类型) pkcs12 # demo - debug key keytool -genkey -v -keystore docs3d.debug.keystore -storepass a123456 -alias docs3ddebug -keypass a123456 -keyalg RSA -keysize 2048 -validity 10000 -dname "C=CN, O=atibm, CN=Docs3d Debug" # demo - release key keytool -genkey -v -keystore docs3d.release.keystore -alias docs3drelease -keypass a123456 -storepass a123456 -keyalg RSA -keysize 2048 -validity 10000 -dname "C=CN, O=atibm, CN=Docs3d Release" # 执行结果 正在为以下对象生成 2,048 位RSA密钥对和自签名证书 (SHA256withRSA) (有效期为 9,999 天): CN=AT, O=BJ, C=CN
- 编辑器设置
- 编辑器>导出>android
- JDK路径:从环境变量JAVA_HOME自动加载
- SDK设置:手动填入SDK路径
- 调试签名:*.keystore文件路径
- 编辑器>导出>android
- 导出设置
- 项目>导出:添加android
- 项目>导出>Android(可执行的)
- 调试和发布的签名设置,用户名和密码,使用签名文件生成时的参数值
- 导出时报错
- keytool invalid keystore format
- 使用studio的keytool生成:"Android Studio 2024.2.1.12"\jbr\bin\keytool.exe,#无效
- 更换系统的JDK版本:检查D:\codeAndroid\studio\Android Studio 2024.2.1.12\jbr\bin\java.exe的版本号,安装对应jdk #无效
- 更换studio的jdk版本:studio>设置>build>gradle: jdk选择跟生成key的jdk环境一致 #成功!!!
- keytool invalid keystore format
实战
脚本
- 日志 logger
Demo
01_docs_2d
- 设置大小
- 项目>显示>窗口:宽长=480*720,拉伸为canvas_items,比例keep
- Player 玩家
- 本节点 Area2D 玩家范围侦测
- 子节点 AnimatedSprite2D 动画效果,属性桢添加桢,往桢添加png并设置缩放
- 子节点 CapsuleShape2D 用于判断碰撞,属性形状添加自身,2D调整蒙版覆盖png
- 关联脚本 player.gd
- 暴露速度属性:@export var speed = 400 # 声明后,在检查器面板会出现speed 参数
- 暴露攻击信号:signal hit # 声明后,在节点面板会出现hit信号
- 玩家操作定义:项目设置>输入映射,定义动作绑定按键
- 脚本监听操作:在gd里用Input.is_action_pressed("move_right")
- 移动处理
- Vector2来产生方向和速度
- $AnimatedSprite2D.flip_来控制移动方向的动画翻转
- $AnimatedSprite2D.play()播放
- velocity.normalized()来防止斜向速度不一致
- position.clamp()来防止跑出画面
- 碰撞处理:双节player节点的信号body_entered(body: Node2D)
- Mob 怪物
- 本节点 RigidBody2D
- 重力设为0,不会自动坠落
- 碰撞的遮罩1取消,确保怪物不会相互碰撞
- 子节点 AnimatedSprite 增加fly swim walk 三个动画
- 子节点 CapsuleShape2D 属性添加自身,2D调整蒙版覆盖png
- 子节点 VisibleOnScreenNotifier2D 信号screen_exited超出屏幕时实现怪物消失
- 本节点 RigidBody2D
- Main 主场景
- 本节点 Node 用于处理游戏逻辑,不需要2D功能,所以不用Node2D
- 子节点 ColorRect 背景色,属性>布局>锚点: 整个矩形覆盖全图(用textureRect则背景图)
- 子节点 Player 拖拽进来关联到main下面
- 子节点 MobTimer wait time属性=0.5,关联_on_mob_timer_timeout
- 子节点 ScoreTimer wait time属性=1,关联_on_score_timer_timeout
- 子节点 StartTimer wait time属性=2,one shot启用,关联_on_start_timer_timeout
- 子节点 StartPosition(Marker2D) position属性=240, 450
- 子节点 MobPath(Path2D) 怪物刷行的区域,2D视图,添加4个顶点,点闭合
- 孙节点 MobSpawnLocation(PathFollow2D) 循着path自动旋转,用来产生随机位置
- 关联脚本 main.gd
- 暴露怪物场景属性:@export var mob_scene: PackedScene
- 关联三个计时器信号、玩家击倒信号
- 子节点 HUB 拖拽进来关联
- 子节点 Music(AudioStreamPlayer) 设置Stream属性选择音频(mp3,),点三角下拉选唯一化,点音乐文件勾选循环,可以无限播放(有ffmpeg工具转换)
- 子节点 DeathSound(AudioStreamPlayer) 死亡音效
- HUD 玩家信息
- 本节点 CanvasLayer 玩家信息,覆盖到游戏画面上层
- 子节点 ScoreLabel 得分
- 节点属性>主题覆盖>字体 选择资源里的Xolonium-Regular.ttf
- 子节点 MessageLabel
- 子节点 StartButton,关联main.gd的new_game
- 子节点 MessageTimer 消息计数器
02_docs_3d
- assert:3d模型glb文件
- 操作设置:四个方向和跳
- 设置分辨率720*540
- layer层定义三层为player enemies world(碰撞:层=物理所在层,遮罩=监听层)
- main.tscn
- 本节点 Node 定义root节点为活动场景
- 子节点 StaticBody3D 地板
- 属性:物理层定义为world,遮罩空
- 孙节点 StaticBody3D 定义地板的形状,节点属性>形状:BoxShape3D 生成立方形状,点这个shape后可设置大小60m*2m*60m
- 孙节点 MeshInstance3D 定义地板的视觉效果,节点属性>网格:BoxMesh 立方体,大小也是60*2*60,开启U磁铁吸附功能,鼠标左键按住Y轴方向的绿色箭头,下移露出示意网格(节点属性>变换>位置:Y=-1m)
- 子节点 DirectionalLight3D 光照
- 属性:Light3D>阴影>法线偏置=1
- 子节点 Marker3D
- 属性:X轴旋转-45度
- 孙节点 Camera3D 摄像头视野,设置Z轴偏离距离19m,正交阴影大小19m
- 子节点 Path3D 怪物刷新路径
- 孙节点 PathFollow3D 路径连接(path点的zyx位置都非常重要,其中y高度会影响怪物刷新高度,从而影响怪物的倾斜度,以及和玩家碰撞形状的高低关系,影响击杀怪物和玩家被击杀的判断)
- 子节点 player
- 在main上右键选择实例化,关联进来
- 子节点 Control
- 属性:主题>新建theme>点开可以选择可视化主题类型
- 孙节点 Label 用于显示文字
- 关联脚本 main.gd
- 暴露属性 mob_scene 并将mob.tscn拖入该属性
- player.tscn
- 本节点 CharacterBody3D 身体
- 由玩家控制而非物理引擎,具有环境碰撞,物理层player,遮罩enemies world与怪物和世界碰撞
- 子节点 Node3D 承载3D模型
- 本节点的变换属性Y轴可以控制玩家展示的高度
- 将player.glb模型拖入,会自动产生一个孙项实例
- 子节点 CollisionShape3D 碰撞形状
- 子节点 Node3D 刷怪的外围路径
- 孙节点 MeshInstance3D 设计具体的网格
- 子节点 Area3D 定义被碰撞到会受伤的区域
- 节点属性 monitoring 可检测来自别人的碰撞-开启,monitorable 可被别人检测-关闭,碰撞层-关闭,碰撞监听遮罩-改为2即怪物层(当怪物碰到它时,会有信号)
- 孙节点 CollisionShape3D
- 子节点 AnimaltionPlayer 动画特效
- 新建动画,点亮自动播放,点亮循环,左侧输入框的时长设为1.2秒
- 到CharacterBody3D 身体节点的属性,每个属性右侧有钥匙图标,点击为这些属性建立动画效果
- 变换Transform > 位置 Position
- 初始状态,点击一次钥匙,创建position动画轴,添加桢1,移动到0.3秒
- y=0.65,点击一次钥匙,创建桢2,移动到0.7秒
- y=0.35,点击一次钥匙,创建桢3,移动到1.2秒
- 变换Transform > 旋转 Rotation
- 初始状态,点击一次钥匙,创建rotation动画周轴,添加桢1,移动到0.1秒
- x=8,点击一次钥匙,添加桢2,移动到0.5秒
- x=-9,点击一次钥匙,添加桢3,移动到1.2秒
- 缓动效果设置
- 选中p轴桢1和r轴桢1:属性>平滑曲线:0.42,即快进缓出
- 选中r轴桢2:属性>平滑曲线:0.44
- 变换Transform > 位置 Position
- 关联脚本 player.gd
- 移动控制
- 本节点 CharacterBody3D 身体
- mob.tscn
- 本节点 CharacterBody3D 身体
- 物理层enemies,遮罩层空,表示怪物相互间穿越
- 子节点 Node3D 拖入mob.glb
- 子节点 VisibleOnScreenNotifier3D 怪物离屏信息
- 子节点 AnimaltionPlayer 动画特效
- 管理动画,新建库,全局库
- 关联脚本 mob.gd
- 玩家操作转为direction
- direction转为velocity向量
- 赋值给角色并执行运动
- 本节点 CharacterBody3D 身体
- MusicPlayer.tscn
- 本节点 AudioStreamPlayer 背景音乐
- ogg音轨拖到流属性里,autoplay勾选
- 项目>全局>自动加载:选择该场景,添加
- !
- 本节点 AudioStreamPlayer 背景音乐
03_bilibili_tilemap
- 解析地砖:新建图块集后,将图片拖入图块集,弹窗点是则自动切割地砖
- 2D→2.5D:TileMapLayer子节点>节点属性:新建图块集>图块形状选Isometric>图块大小:比如64*32这样,放入2.5D地砖就有2.5D效果。要求给的地砖纹理就有2.5D效果才行
- 多层地图:旧版本在节点属性>排序>新增图层,每个图层分别设置Z索引高度;新版4.3每建立一个TileMapLayer节点就是一个图层
- 地形集:属性>地形集>添加元素新增一个集合;再到tileset>绘制>地形>选择地形集>多选图块,并点亮地砖部分(内部)
04_bilibili_reburn
- 像素风格
- 纹理设置:需要设置配合一下,在项目设置>渲染>纹理:默认纹理过滤改为Nearest
- 开始菜单
- 子节点快速创建:可以复制粘贴,设置布局时,可以对x或y输入数字加减,控制完美的间距
- 按钮样式:可以对button子节点的canvasItem的可见性,调制,透明为0后,再用设计图片放这就行了
- 跳转:按钮信号关联方法内,get_tree().change_scene_to_file("res://scenes/startchoice.tscn")
- 选择页
- 玩家属性
- 属性存储:新建孤立gd脚本,用于管理玩家属性,并设置项目全部变量
- 属性写入:新建关联脚本,用输入信号触发写入属性,PlayerDB.set_attr(name, value)
- 属性刷新:$main_div/attr_div/attr_value/CHA.text = str(value)
- 属性按钮:关联方式
func _ready() -> void: register_all_button() func register_all_button(): # 遍历 attr_reduce 下的所有按钮,动态连接信号 for button in $main_div/attr_div/attr_reduce.get_children(): if button is Button: button.pressed.connect(_on_reduce_pressed.bind(button)) for button in $main_div/attr_div/attr_increase.get_children(): if button is Button: button.pressed.connect(_on_increase_pressed.bind(button))
- 玩家属性
- 商店页
- UI层:遍历inventory的item放入menu的grid
- 数据层:inventory放入道具item.tres
- 模型层:item_base定义模型属性,实例化出道具item.tres
todo:
- 商店交互,购买和属性生效,道具的格子效果
- 玩家拆为2层,model,真实玩家,固化道具,固化天赋;模拟玩家,继承道具,继承天赋,模拟道具,模拟天赋,交互应用天赋,装备道具
- 拆出天赋,形成天赋model基本属性
- 天赋单独拆出来model