注
对于会员 bitca.cn 的两篇 Godot 做了整合。
脚本部分
关于 _ready
在 _ready 中你可以访问完整的 tree,但是你不能更改 tree 的结构。当我想在 _ready 中把一个子物体移动到另外一个地方时,操作总是无法成功的。这个时候有两种方法:
- 使用 call_deferred(函数名)
- 使用 yield(get_tree(),"idle_frame")
相关阅读:
https://godotengine.org/qa/7336/what-are-the-semantics-of-call_deferred
GDScript 关于下划线
原来 add_child 可以用 addc... 来自动补完的,不需要输入下划线,排除了下划线对输入的影响,这样的话使用下划线的函数名就方便了
3.1 typing
https://godotengine.org/article/optional-typing-gdscript
现阶段 signal 函数的参数还没有 type hints
Editor Tool
各种资源类型也可以方便的在脚本中设置为编辑器参数:
export(Material) var output_material
Signal
在连接 signal 到函数时,一定要确保接收函数的参数数量跟事件的参数一致,否则可能无法触发,在 connect 时一定要查看 signal 的参数。
关于 _process 和 _physics_process
https://docs.godotengine.org/en/3.0/getting_started/step_by_step/scripting_continued.html
_process 的执行时间是在每次帧绘制完成后,可以使用 set_process() 来打开或者关闭,只要写了这个函数,默认是打开执行的。而 _physics_process 则是在物理引擎计算之前执行,而物理引擎的计算间隔是固定的,更新频率可以自行设定。
_draw()
https://docs.godotengine.org/en/3.0/tutorials/2d/custom_drawing_in_2d.html
_draw() 只会执行一次,画出来的内容会缓存并一直显示,如果需要更改,可以执行 update(),如果需要每帧执行,那么可以把 update 放到 _process 里
setget 没有触发?
如果在本脚本范围想要触发 setget,需要在变量面前加 self.
export var 的数值范围,参看:
# Allow integer values from 0 to 20. export(int, 20) var i # Allow integer values from -10 to 20. export(int, -10, 20) var j # Allow floats from -10 to 20, with a step of 0.2. export(float, -10, 20, 0.2) var k # Allow values y = exp(x) where y varies between 100 and 1000 # while snapping to steps of 20. The editor will present a # slider for easily editing the value. export(float, EXP, 100, 1000, 20) var l
场景转换
https://godotengine.org/qa/24773/how-to-load-and-change-scenes
Autoload
如果你设置一个场景(.tscn)为 singleton,那么这个场景上的脚本函数会因为这个 scene 没有 instance 而无法执行,所以应该设置一个 .gd 为 singleton,然后通过这个 .gd 来 preload 并 instance 一个 .tscn。
Editor 相关
GDScript 脚本中只要加入 tool 关键字就会在编辑器中执行
包括子物体的 Visible 显示都可以在编辑器的界面中实时反馈了,要研究的是:
- tool 所放置的位置有没有关系,之前的代码会不会在编辑器中运行
- extend 的脚本跟 tool 的关系,(测试是可以运行的)
检测当前是否在 Editor 中运行,使用 Engine.editor_hint 检查
https://docs.godotengine.org/en/3.0/classes/class_engine.html?highlight=editor_hint
输入法问题
在现在的版本中,在使用中文输入法后,godot 会处在一种 ctrl 键被按下的状态(至少在 windows 平台下如此),这个时候需要按一次 ctrl 键来恢复正常的输入。
操作效率
参看 油管播主 GDQuest 的视频:
Fast Project Navigation Tips in Godot (beginner tutorial)
Make Sense of the Code Reference in Godot (beginner tutorial)
渲染相关
Viewport 内的 Node 无法使用移动工具
这个官方还没有解决:
https://github.com/godotengine/godot/issues/20619
https://github.com/godotengine/godot/issues/17739
viewport 中不显示子物体内容?
在使用 viewport 时一定要给一个 camera 配合这个 viewport(最近的一个),否则这个 viewport遇到别的摄影机时就会用别的摄影机.
实现 mask 的尝试
这里有 light mask 的演示 :https://www.youtube.com/watch?v=e5EUZGbrMRY
但是,新渲染引擎中这个功能失效了,需要等待下个版本修复:https://github.com/godotengine/godot/issues/8685
现在的效果是这样:
已经实现半透明 mask,问题是颜色被灯光叠加了
灯光相关设置为:
材质需要为 CanvasItemMaterial:
更新 : 我发现indienova已经有人发过相关的笔记:https://indienova.com/groups/post/29324
问题在于,要做灯光 mask 需要你的图片的透明通道,我的那个纯黑白图当然就不行了,修改一下成功了:
Light2D
会照亮相应的 Light Mask 层
CanvasModulate
这个节点会调整最近一个 viewport 的颜色,不过只要有 Light2D 存在就会失效
Outline Shader
https://github.com/steincodes/godot-shader-tutorials/blob/master/Shaders/outline.shader
这个 Shader 用来做人物高亮选择框,不过最好配合 Viewport 使用,在 Sprite 中使用这个 Viewport 作为贴图,然后再加 Shader 使用
两个数值这么调,正好是一个像素
Material 多个物体要使用同一个材质
多个物体要使用同一个材质,可以设置为 local to scene ,这样这个材质就单独在这个内在场景中实例化了。多个物体使用一个材质时不会互相影响。
visual shader
用 visual shader 的时候注意,默认的shader方式是3d的,2d的需要改这里
Mode : CanvasItem
图像相关
画面的缩放选项
最常规的 2D 像素缩放设置: Mode=2D,Aspect=keep
关于像素图片资源的设定
第一次打开 godot 3.1 记得将 Import 界面单独放到 Inspector 旁边,否则你有可能会忽略图片资源的导入设置,特别是像素图的 Filter 选项,有可能在视图中显示是不抗锯齿的,实际运行使用的还是 import 里面的配置。另外这里有 Preset 是可以直接设置为 2D Pixel 的。
在低像素分辨率下得到高清字体的方法
先设置字体到合适大小,比如 12,然后根据需要乘于倍数比如 12x4=48,然后将 scale 值设置为 1/4 也就是 0.25。那么比如你的画面分辨率是 480x270 , 1920x1080 的四分之一,那么实际渲染的字体效果在全高清下是不会看到锯齿的。
UI 相关
UI想要不跟随摄影机移动?
添加一个 CanvasLayer 节点,把相关的 UI Node 放里面
CanvasLayer 上的 Node 受到了 2D 光照影响?
需要去掉 UI Node 的 Light Mask
打开 2D 光照后 CanvasLayer 下的文字渲染不出来?
把 Lyaer 调为 0,是什么机制现在还不清楚
Debug
运行时切换到显示 Remote 的 Tree 和每个节点的属性
这是个不小发现,原来我总是需要打印出场景的树结构,其实运行时在这里可以切换到当前运行的树结构状态:
而且节点的每个属性都是可以查看和修改的!!!
变化是同步的:
节点与场景构造
注意场景 inherited 某个 scene 会对属性进行覆盖性调整
有时调整源 scene 的地方,要回头到 inherited scene 中查看是不是被覆盖的。
节点的 Modulate 与 Self Modulate 的区别
Modulate的 调整会影响子物体,而 Self Modulate 则不会。
输入相关
关于 input
https://docs.godotengine.org/en/3.0/tutorials/inputs/inputevent.html
输入事件有个检查顺序,可以看文档中的图。
- 首先是节点上的 _input(ev),这个事件可以用 Node.set_process_input() 来禁用,如果需要不再往下传递,可以使用 SceneTree.set_input_as_handled()。
- 然后再到 GUI 各 control 的 Control._gui_input() ,可以通过 Control.accept_event() 停止往下传递。同时可以使用 Control.mouse_filter (参数界面上也有设置)来设置这个控件是否响应鼠标事件。
- 然后没有被“消费”的事件,轮到 unhandled input callback 来处理,所以游戏中的操作尽量选择这个来进行处理,特别是需要 GUI 阻断的。
更多详细描述可以看文档。
一个重要的事实:
当你的游戏输入使用 _unhandled_input 来处理鼠标,而且屏幕上覆盖有可见的控件时,鼠标事件会被阻断,这个时候你要设置 MouseFilter 为 MOUSE_FILTER_IGNORE。在使用全屏的控件根物体时,可选择这个选项。如果是一个面板,可以选择 pass ,这个会阻止鼠标事件传递到 _unhandled_input。
https://docs.godotengine.org/en/3.0/classes/class_control.html#enum-control-mousefilter
在节点上取得鼠标在世界中的坐标
func _input(event): if event is InputEventMouseButton and event.pressed and event.button_index == 1: print("Mouse Click at: event.position", event.position) print("Mouse Click at: ", get_global_mouse_position())
感谢编辑做的整合,其实是不小心点错了投稿...
@bitca.cn:国内Godot相关文章不算多,这么好的干货笔记,还打算藏着不投稿(狗头)
这是好的