Godot-StartUP

创建于:2018-07-28

创建人: Justus

44 信息 140 成员
讨论基于Godot以及Unity引擎的游戏开发经验,理论和最佳实践。共享一些通用思路以启发另一种生产工具中的实践。独立开发群QQ: 122017359
Justus@Godot-StartUP 的内容(查看所有内容
发文原则保持不变,鼓励笔记型日志。
Justus 2022-04-11

小组不再限制加入条件。通过了所有加入请求。

发文原则保持不变,鼓励笔记型日志。

另外小组说明中的qq群目前不处于开放状态。有特别需要加入的独狼开发者可以私信加入。

小组说明
Justus 2018-09-28

1. 本小组用于笔记收集,作为资料目录使用。

2. 请先发布个人日志再推送至小组,而后大家就可以通过帖子的原文链接追溯原文的更新。

3. 日常讨论在qq群进行,鼓励在日常讨论后记笔记,汇聚成文以回馈社区。

    Godot独立开发游戏技术群:QQ: 122017359

    如果你正在使用Godot制作自己的独立游戏,需要和一起奋斗的小伙伴们互相交流技巧,请加入我们。

Godot实践 Q&A
Justus 2018-09-28

Godot Q&A

Godot 3.0.6

1. _enter_tree() vs _ready()

[reddit] enter_tree() vs. ready(), etc. Are there rules of thumb regarding which initialization function to do my housekeeping?

2. 如何用脚本connect signals?

[reddit] explain to me how to use the signals in Godot, please.

3. collision layer 和 collision mask有什么区别

[GodotQ&A] What's the difference between Collision layers and Collision masks?
[GodotQ&A] Collision masks and its propper uses

4. 如何在pc上打开触屏模式?

Project Settings->Display->Emulate Touchscreen
[GodotQ&A] How can i show touch screenbuttons only on android devices?

5. 为什么tilemap会闪烁

Open issue, 把quadrant size 设为1就不闪了
[GithubIssue] Tilemap/draw_rect random flickering with Nvidia drivers

6. windows平台的导出exe图标设置没有效果

godot已知bug,自己用resource hack改

Resource Hacker 简介

A freeware resource compiler & decompiler for Windows® applications
Resource Hacker HomePage

7. NavigationPolygonInstance 为什么无法多个同时起效?

注意拼接要严丝合缝,即相邻边拥有共同顶点。
[Blog] [godot]navigation2d的一些坑

8. 如何用print格式化输出?

print("%s" % value)  
print("%s...%s" % [value1,value2,...])

9. 两个引用所指的碰撞对象是不是同一个,有什么办法判断吗?

Resource Id.

CollisionObject.get_rid().get_id()
CollisionObject2D.get_rid().get_id()

10. 有什么方式记录下collisionLayer的用途约定么?

有。给每个layer命名。
Project Settings->General->Layer Names

11. free() vs queue_free()

12. 为什么RayCast/RayCast2D 只有 Collision Mask而没有Collision Layer? 这意味着什么?

这意味着其他人不能决定自己是否和raycast碰撞,只有RayCast可以决定自己打算和处于哪些Layer的对象碰撞。

13. 为什么Godot没有现成的FSM?这会影响它的易用性么?

J: 我不知道。不会影响易用性。
因为动画系统通常包含着一个天然的FSM,除了transition。Godot 在之后的版本中会加入一个与动画系统协作的状态机。但这并不是很有必要。
因为对于简易的状态机而言,几乎总是能用enum加一个状态转移方法来完成。对于复杂的状态机而言,动画系统的状态和实际的逻辑状态机通常会不一样,并且FSM在并发和层次用途同时出现的情况下并不是最好的选择。 个人推荐仅在简单和并发状态下考虑状态机。通常层次状态机的场景你可以通过一些设计来改变成并发状态。
如果你真的寻求复杂的决策实现并且被层次状态机的可扩展性弄得精疲力尽,那么推荐使用行为树(behavior tree)

14. 什么是行为树?Godot 3有现成的实现么?

一种AI算法。
一种梳理逻辑决策的解决方案。
它解决的问题与复杂的状态机类似。通常由一个树结构+黑板来实现。
Godot中没有内置的实现。有其他开发者提供的插件实现(Godot 3可用)。
开发者务必阅读链接文章。如果你毫无编程经验,那么请向你家的软件设计师寻求符合你需要的简单解释。在一些游戏引擎中会内置BT功能,他们的文档也许是不错的选择。

行为树参考:
[Wikipedia] Behavior tree (artificial intelligence, robotics and control)
Behavior trees for AI: How they work
[SO] Behavior Tree Implementations

15. 默认函数_xxxx在子类中如何被调用?

总是在子类的覆写实现之前自动被调用。

Remember that default functions like _init, and most notifications such as _enter_tree_exit_tree_process_physics_process, etc. are called in all base classes automatically. So there is only a need to call the function explicitly when overloading them in some way.

[GodotDocs] GDScript

16. 如何设置新的随机种子?

randomize()

17. 如何设置断言?

assert a==b

18. 如何获取run time type?

is
get_class()

19. 如何脚本创建timer?

get_tree().create_timer(1.5)

20. 某个节点如何获取编辑他的场景的根节点?

Node.owner

21. 如何使用AutoTile?

[GodotQ&A] How do I use the AutoTile in Godot 3.0?

22. 使用其他线程创建实例为什么感觉这么慢?

对,是个已知问题。
[GithubIssue] Multithreaded instancing performance (RID caching needs to be completed) #10970 
[blog] 关于godot中多线程生成场景加入主场景问题

23. Tiled可以和godot 3一起工作么?

可以,AssetLib搜索插件Tile Map Importer。
[Youtube] How to Import Maps from Tiled in Godot
[reddit] Importing from Tiled with collisions?

24. set_process,set_physics_process,set_process_input 是默认为true的吗?

是的。不同于Godot 2, 在Godot 3中他们默认为true。

25. 什么情况下属性的setter,getter才会被调用?

外部访问时。内部用self.prop1的方式访问时。

26. gdscript 有哪些内建函数可用?

[GodotDocs] @GDScript

27. gdscript 有访问限定符么?没有的话如何控制访问权限?

没有 access modifier.
语法上不能控制。设计上依然可以通过良好的约定和命名法来表征设计约束。
Keep it simple and stupid.
[Widipedia] Access Modifiers
KISS (Keep it Simple, Stupid) - A Design Principle

28. 为什么我的派生场景无法访问父场景的成员变量?

情况之一: 如果你的父场景自带一个脚本,派生场景不带脚本,会无法访问。这种情况下,应取消父场景中脚本的绑定,在子场景中重新绑定一次父脚本或者创建一个继承于父脚本的新脚本。
[GithubIssue] GDScript: Parent variables aren't accessible in sub classes

29. 为什么godot编辑器对我的键盘输入没反应了?

切换完输入法以后请额外按一次Ctrl以解除这个状态。

30. 如何全局自定义鼠标光标? (为什么它不工作?)

TBD
[GodotDocs] Customizing mouse cursor

31. 关于svg格式的支持

[GodotQ&A] Is there .SVG file support for Godot?

32. 如何得到String中的每一个字符?

[GodotQ&A] How to split a string character by character?

33. 如何得知node是否被free?

[GodotQ&A] How to know a node is freed (or deleted)

34. 如何检查手柄是否连接?

[GodotQ&A] Check if Controller connected or not

35. 如何检查一个变量是否存在?

if "varName" in get_parent(): print("varName is defined in parent!")
[GodotQ&A] Check if script of a node has variable

36. 为什么游戏总是会对手柄输入进行响应,即使窗口已经失去焦点?有什么办法能控制是否屏蔽这种行为么?

取决于OS的处理,通常OS总是会把手柄响应发给程序,而键盘输入则不同。
如下方法可以获知焦点状况。

func _notification(what):
    if what == MainLoop.NOTIFICATION_WM_FOCUS_OUT: 
        Unfocused = true
    elif what == MainLoop.NOTIFICATION_WM_FOCUS_IN: 
        Unfocused = false

[GithubIssue] Games receive joypad input even if the game window is not focused

37. 如何导出Android apk?

导出三件套

Godot 3.1

1. 如何使用3.1新特性 typed GDScript?

LEARN TO WRITE TYPED GDSCRIPT IN GODOT 3.1

Networking

1. localhost、127.0.0.1 和 本机IP 三者的区别?

[知乎] localhost、127.0.0.1 和 本机IP 三者的区别?
[百度知道] localhost,127.0.0.1 和 本机IP 三者的区别

一般话题

1. 如何在GLSL中将RGB值转化为HSV?

[SO] From RGB to HSV in OpenGL GLSL

2. 如何描述FSM?该从哪里开始?

可以使用UML来描述。
[Wikipedia] Unified Modeling Language
[Wikipedia] UML state machine
State Machine Diagram Tutorial
[blog] 【学习小记】UML——状态机图

Git

1. fast forward 是什么?

Git fast forwards and branch management

2. rebase 是什么?

Merging vs. Rebasing
Don't Be Scared of git rebase

MarkDown

  1. 关于MarkDownDaring Fireball: Markdown Syntax Documentation

Other Tools

1. 有哪些开源免费的绘画工具?

GIMP, Krita, Aseprite
GIMP - GNU Image Manipulation Program
Krita | Digital Painting. Creative Freedom.
Aseprite - Animated sprite editor & pixel art tool

2. 有哪些tilemap 编辑器?

Tiled Map Editor | A flexible level editor
[Docs] Tiled Documentation

3. 制作系统UML图和FSM图有什么工具吗?

VP Online
Lucidchart: Online Diagram Software & Visual Solution

4. 常见游戏术语的定义

Gaming Dictionary

5. 动作设计软件

MakeHuman
[Youtube] MakeHuman 1.1 -- A Completely Free 3D Character Creator
design doll
[Youtube] [TUTORIAL] Design Doll
iclone
Daz3D
Daz3D Documentation Center

6.函数绘制

Desmos

7.界面设计原型工具

Pencil Project

(转发自:原日志地址
[Godot 3.1][GDScript][译]将gd脚本注册为class
Justus 2018-09-28

Register scripts as classes

Godot支持名为“Script Class”的特性允许我们将个人的脚本注册给godot编辑器使用。而默认情况下,你只能通过直接加载的方式来访问未命名的脚本。
通过在关键字class_name后面添加类名的方式,你可以给一个脚本命名并且将其作为一个类型注册到godot编辑器。你还可以添加一个逗号和可选的图片路径将其作为类的图标。此后你就可以在创建Node和Resource的对话框中找到你新定义的类了。

extends Node

# Declare the class name here
class_name ScriptName, "res://path/to/optional/icon.svg"

func _ready():
    var this = ScriptName           # reference to the script
    var cppNode = MyCppNode.new()   # new instance of a class named MyCppNode

    cppNode.queue_free()

doc_picture


Warning

在 Godot 3.1 中:

  • 只有 GDScript 和 NativeScript(C++和其他GDNative-powered的语言),能注册脚本。
  • 只有 GDScript会为每个被命名的脚本创建全局变量

参考

[GodotDocs] Scripting (continued)

(转发自:原日志地址
[Godot] Godot 3 快捷键参考
Justus 2018-08-11

[Godot] Godot 3 快捷键参考

版本

Godot 3.0.6

常用快捷键

Canvas Item Editor

快捷键 描述
F 居中选取对象
V 更改pivot至当前鼠标位置
Ctrl + 鼠标拖曳 以pivot为中心旋转当前对象
Alt + 拖曳边框缩放点 保持选中目标中心位置不变进行缩放

Animation Player Editor

快捷键 描述
A 反向播放动画
S 暂停播放动画
D 正向播放动画

全部快捷键

Editor-> Editor Settings-> Shortcuts

参考

[GodotQ&A] Undocumented Shortcuts

(转发自:原日志地址
[GDScript]字典(Dictionary)的顺序
Justus 2018-08-05

[GDScript]字典(Dictionary)的顺序

背景介绍

GDScript作为godot首选的脚本语言有着与python类似的语法。Dictionary自然也是必不可少的容器结构。然而多数语言的Dictionary实现通常基于hash table, 无法实现有序排列。通常遇到有序需求时我们会选用Array来替代。

按插入的顺序获取key

godot的Dictionary3.0版本中追加了一个特性:遍历字典时保持插入顺序。记录以供参考。

例子

var dict = {}
dict["3"] = 1
dict["2"] = 1
dict["4"] = 1
dict["5"] = 1
dict["1"] = 1
dict.erase("4")
dict["4"] = 1

print("dict = ", dict)
for each in dict.keys():
print("curKey = ",each)

输出结果:

dict = (1:1), (2:1), (3:1), (4:1), (5:1)
curKey = 3
curKey = 2
curKey = 5
curKey = 1
curKey = 4

参考

1.[Wikipedia] Hash table
2.[Godot Q&A] Ordering / sorting objects in a dictionary?

(转发自:原日志地址
[译]在godot中利用yield函数来使用协程(Coroutines)
Justus 2018-07-30

Coroutines with yield

GDScript 提供yield内建函数用以支持coroutines。调用yield()将会立刻从当前函数返回,同时将这个函数的当前状态冻结作为返回值。如果之后通过返回值得到的对象调用resume(继续)方法,就会继续从上个冻结状态执行下去并返回下一个返回值。一旦调用过resume方法后,之前的得到的状态对象就失效了。例子如下:

func my_func():
   print("Hello")
   yield()
   print("world")

func _ready():
    var y = my_func()
    # Function state saved in 'y'.
    print("my dear")
    y.resume()
    # 'y' resumed and is now an invalid state.

输出结果:

Hello
my dear
world

yield()resume()调用之间我们也可以传递参数,例子如下:

func my_func():
   print("Hello")
   print(yield())
   return "cheers!"

func _ready():
    var y = my_func()
    # Function state saved in 'y'.
    print(y.resume("world"))
    # 'y' resumed and is now an invalid state.

输出结果:

Hello
world
cheers!

Coroutines & signals

与signal(信号)机制结合使用才会发挥yield真正的长处。 yield方法可以接受两个参数,一个对象引用,一个信号名称。效果是:收到该信号时,重新开始执行该协程。例子如下:

# Resume execution the next frame.
yield(get_tree(), "idle_frame")

# Resume execution when animation is done playing.
yield(get_node("AnimationPlayer"), "finished")

# Wait 5 seconds, then resume execution.
yield(get_tree().create_timer(5.0), "timeout")

协程本身使用名为completed的信号来表达他们转移进入了一个无效状态,例子如下:

func my_func():
        yield(button_func(), "completed")
        print("All buttons were pressed, hurray!")

func button_func():
    yield($Button0, "pressed")
        yield($Button1, "pressed")

my_func仅当两个button按钮都被按过以后才会继续执行。

参考

  1. [GodotDocs] GDScript
  2. [Wikipedia] Coroutine
  3. [Wikipedia] Subroutine
(转发自:原日志地址
一种GDScript语言符号的命名策略
Justus 2018-07-29

一种GDScript语言符号的命名策略

GDScript介绍

GDScript是一种godot游戏引擎所支持的自制的python-like脚本语言,学习成本低,与引擎的功能结合完美,是godot引擎本身“All-in-one”理念所不必可少的组成部分。 在godot项目工程中,由GDScript脚本的后缀名为.gd

GDScript的几个设计决策

gdscript设计之初便融合于面向对象设计。一个.gd脚本文件即为一个class,如果这个文件依附于某个godot节点,那它便是继承自那个节点类型的派生类。这种设计方式也比较完美的避开了oop程序设计的初学者滥用global变量的风险。Godot依旧设计了Autoload这种方式来的提供那些生命周期与程序一样长的对象实例的访问。

即使是Autoload也无法阻止任何人破坏封装性

然而,gdscript语言不设置任何access modifier(or access specifier). 在这里,我们无法从语言语法规则上指定成员的是否公开还是私有,是否受保护。 类的设计者创建了诸多私有成员,只是因为其中的某些没有设置setter/getter就被其他人(或者几个月后的自己)随意访问的情况几乎无法避免。对于成员函数而言,更是毫无任何办法进行保护。这个小节的标题也正是其中一个后果。

利用命名来表征自己的设计意图

因此,在我的项目中,采用了如下的命名方式来表现设计语义。在语法上没有约束力,只是为了表达更多的语义信息。

  • _
    godot内置函数的前缀,如果在你的类中出现了这样的函数,便是进行了一次overwrite,相当于c++中的virtual关键字,java中的默认函数覆写(overwrite)。
  • __
    双下划线,表明私有,变量与成员方法均适用。
  • 变量名全大写常数。
  • 所有export变量均不以 __ 开头

后续效果观察

TBD

参考

[GodotDocs] GDScript

(转发自:原日志地址
在Godot中利用Tween节点指定Easing function来控制参数的变化曲线
Justus 2018-07-28

在Godot中利用Tween节点指定Easing function来控制参数的变化曲线

介绍: 什么是Easing function

Easing function 用以描述参数值随时间而改变的变化率。 现实生活中的物体几乎不会以维持常数的速度移动,也不会瞬间开始和停止。当我们打开一个抽屉时,一开始的速度非常快,在拉出来之后慢下来。将物品跌落地板时,它一开始会向下加速,然后在击中地板后回弹。

Easing funcion 是一种描述变化的曲线方程,非常适合用来描绘生动的运动过程。在参考链接中我们可以找到许多有趣的easing function。而Godot的Tween节点也提供了用于指定Easing方式的参数。

Tween节点

godot提供了一种tween节点来简化插值变换的实现。以下代码块是比较常见的用法。

...
onready tween = $Tween

func start():
    tween.interpolate_property(object, propertyName, initial_val, final_val, duration, trans_type, ease_type, delay)
    tween.start()
...

被指定的<object> 中名为 <propertyName> 的成员变量将会在<duration>时间内从初始值变化到最终值。具体的插值规则以及曲线的形态由<trans_type>和<ease_type>共同指定。详细的参数描述请见Tween节点的文档中的EaseTypeTransitionType两个枚举类型。

enum EaseType:
...
enum TransitionType:
...

组合这两个参数可以实现丰富的变化方式,请自行具体实践。

更加丰富的变化方式

如果Tween节点中所有的预设方式还是无法满足要求,那么我们就可以考虑使用AnimationPlay这个节点了,这个工具最佳情况下允许我们以0.02秒的间隔指定任何property关键变化值,可以满足绝大部分的需求。有机会再单独介绍这个节点。

补充说明:property即为inspector面板上可以看到的任何值。

参考:

  1. Easing Functions Cheat Sheet
  2. [GodotDocs] Tween
(转发自:原日志地址
一种Godot项目组织形式
Justus 2018-07-28

一种Godot项目组织形式

近来启动了一个小型项目,完全采用 godot 3的引擎,旨在验证并探索一个完整游戏开发过程中的模块实现。 为了未来这个项目仍然具备一定的价值,需要一种项目组织形式,以对未来的重构和复用保留灵活性。特此记录个人观点,以便于日后反思修正。
Image title

1. 核心思想:

以每个场景的根节点为最小单位,划分独立的文件夹。每个场景文件夹尽可能的拥有独立的assets文件夹,以保留自己的美术资源。

2.根本诉求:

在脱离godot内置编辑器的情况下,可以在操作系统的文件资源理器内以文件夹为单位重新创建新项目作为试验或者复用的沙盒。

3.缺点和优点:

a. 缺点:无法全局管理项目资产
b. 优点:无论是谁,无论开发者自己是否记得住项目组织逻辑,总是可以从一个文件夹入手

4.一些细节应对:

  • a. 允许出现一些以分类为目,或是保存基类为目的的文件夹,比如enemy下保有concreteEnemy1,concreteEnemy2文件夹,后两者才是最小组织单位,但是他们可以被放置于一个分类文件夹enemy下(enemy也可能就是他们的基类)。
  • b. 如何组织godot的特有资源文件格式tres?与外部的资源文件不同,godot可以保存一种tres格式的资源文件。因其特殊性,建议在每个模块文件夹下单独创建tres文件夹保存他们。所谓tres指的是‘text resource’, 这些配置参数原本内嵌于场景文件中,比如animationPlayer,比如dynamic font, 而godot又允许直接将这些文本形式的内容单独保存成资源文件以方便复用,就有了tres格式,因此tres格式是将“文本配置”视作“资源”的格式,因其特殊性,我希望将他与一般外部资产分离,故选用单独文件夹保存。
  • c. 关于模块内资产划分的建议: Texture, Script, Mesh, Animation, AudioStream, Font, Translation等等。

参考:

1. [YouTube] 6 Tips to Better Organize your Godot 3 Projects
2. [GodotDocs] Resources 

(转发自:原日志地址

加入 indienova

  • 建立个人/工作室档案
  • 建立开发中的游戏档案
  • 关注个人/工作室动态
  • 寻找合作伙伴共同开发
  • 寻求线上发行
  • 更多服务……
登录/注册