Godot 学习笔记

作者:bitca.cn
2018-12-20
16 10 2

对于会员 bitca.cn 的两篇 Godot 做了整合。

脚本部分

关于 _ready

在 _ready 中你可以访问完整的 tree,但是你不能更改 tree 的结构。当我想在 _ready 中把一个子物体移动到另外一个地方时,操作总是无法成功的。这个时候有两种方法:

  • 使用 call_deferred(函数名)
  • 使用 yield(get_tree(),"idle_frame")

相关阅读:

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 的数值范围,参看:

http://docs.godotengine.org/en/latest/getting_started/scripting/gdscript/gdscript_basics.html#exports

# 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

输入事件有个检查顺序,可以看文档中的图。

  1. 首先是节点上的 _input(ev),这个事件可以用 Node.set_process_input() 来禁用,如果需要不再往下传递,可以使用 SceneTree.set_input_as_handled()。
  2. 然后再到 GUI 各 control 的 Control._gui_input() ,可以通过 Control.accept_event() 停止往下传递。同时可以使用 Control.mouse_filter (参数界面上也有设置)来设置这个控件是否响应鼠标事件。
  3. 然后没有被“消费”的事件,轮到 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())

近期点赞的会员

 分享这篇文章

您可能还会对这些文章感兴趣

参与此文章的讨论

  1. bitca.cn 2018-12-20

    感谢编辑做的整合,其实是不小心点错了投稿...

    • 83872309 2019-05-18

      @bitca.cn:国内Godot相关文章不算多,这么好的干货笔记,还打算藏着不投稿(狗头)

您需要登录或者注册后才能发表评论

登录/注册