本帖最后由 蚊子 于 2020-8-6 21:52 编辑
Introduction
介绍Before Godot 3.0, the only choice for scripting a game was to use GDScript. Nowadays, Godot has four (yes, four!) official languages and the ability to add extra scripting languages dynamically!
在Godot 3.0之前,编写游戏脚本的唯一选择是使用 GDScript。如今,Godot具有四种(是的,四种!)官方语言,并且能够动态添加额外的脚本语言! This is great, mostly due to the large amount of flexibility provided, but it also makes our work supporting languages more difficult.
这很好,主要是由于提供了大量的灵活性,但是这也使我们支持语言的工作更加困难。 The "main" languages in Godot, though, are GDScript and VisualScript. The main reason to choose them is their level of integration with Godot, as this makes the experience smoother; both have slick editor integration, while C# and C++ need to be edited in a separate IDE. If you are a big fan of statically typed languages, go with C# and C++ instead.
但是,Godot中的“主要”语言是GDScript和VisualScript。选择它们的主要原因是它们与Godot的集成程度,因为这会使体验更加流畅。两者都具有流畅的编辑器集成,而C#和C ++需要在单独的IDE中进行编辑。如果您非常喜欢静态类型的语言,请改用C#和C ++。 GDScriptGDScript is, as mentioned above, the main language used in Godot. Using it has some positive points compared to other languages due to its high integration with Godot:
如上所述,GDScript是Godot中使用的主要语言。由于它与Godot的高度集成,因此与其他语言相比,使用它具有一些积极点: - It's simple, elegant, and designed to be familiar for users of other languages such as Lua, Python, Squirrel, etc.
它简单,优雅,旨在让其他语言(例如Lua,Python,Squirrel等)的用户熟悉。 - Loads and compiles blazingly fast.
极快地加载和编译。 - The editor integration is a pleasure to work with, with code completion for nodes, signals, and many other items pertaining to the scene being edited.
编辑器集成很高兴与之配合使用,节点,信号和许多其他与正在编辑的场景有关的项目的代码完成。 - Has vector types built-in (such as Vectors, transforms, etc.), making it efficient for heavy use of linear algebra.
具有内置的向量类型(例如,向量,变换等),使其对于大量使用线性代数有效。 - Supports multiple threads as efficiently as statically typed languages - one of the limitations that made us avoid VMs such as Lua, Squirrel, etc.
支持与静态类型语言一样有效的多个线程-这是我们避免使用Lua,Squirrel等VM的限制之一。 - Uses no garbage collector, so it trades a small bit of automation (most objects are reference counted anyway), by determinism.
不使用垃圾收集器,因此根据确定性,它只交换了一点点的自动化(无论如何大多数对象都是引用计数)。 - Its dynamic nature makes it easy to optimize sections of code in C++ (via GDNative) if more performance is required, all without recompiling the engine.
如果需要更高的性能,它的动态特性使您可以轻松地优化C ++代码段(通过GDNative),而无需重新编译引擎。
If you're undecided and have experience with programming, especially dynamically typed languages, go for GDScript!
如果您不确定并有编程经验,尤其是动态类型的语言,请使用GDScript!
VisualScriptBeginning with 3.0, Godot offers Visual Scripting. This is a typical implementation of a "blocks and connections" language, but adapted to how Godot works.
从3.0开始,Godot提供了Visual Scripting。这是“块和连接”语言的典型实现,但适应了Godot的工作方式。 Visual scripting is a great tool for non-programmers, or even for experienced developers who want to make parts of the code more accessible to others, like game designers or artists.
对于非程序员,甚至对于想使部分代码更易于其他人(例如游戏设计师或美术师)访问的有经验的开发人员而言,可视化脚本是一个很好的工具。 It can also be used by programmers to build state machines or custom visual node workflows - for example, a dialogue system.
程序员也可以使用它来构建状态机或自定义可视节点工作流,例如对话系统。
.NET / C#As Microsoft's C# is a favorite amongst game developers, we have added official support for it. C# is a mature language with tons of code written for it, and support was added thanks to a generous donation from Microsoft.
由于Microsoft的C#在游戏开发人员中是最喜欢的,因此我们为其添加了官方支持。C#是一种成熟的语言,上面编写了大量代码,并且由于Microsoft的慷慨捐助而增加了支持。 It has an excellent tradeoff between performance and ease of use, although one must be aware of its garbage collector.
尽管必须了解其垃圾收集器,但它在性能和易用性之间有一个很好的折衷。 Since Godot uses the Mono .NET runtime, in theory any third-party .NET library or framework can be used for scripting in Godot, as well as any Common Language Infrastructure-compliant programming language, such as F#, Boo or ClojureCLR. In practice however, C# is the only officially supported .NET option.
由于Godot使用Mono .NET运行时,因此从理论上讲,任何第三方.NET库或框架都可以用于Godot中的脚本编写,以及任何符合Common Language Infrastructure的编程语言(例如F#,Boo或ClojureCLR)中。但是实际上,C#是唯一受官方支持的.NET选项。
GDNative / C++Finally, one of our brightest additions for the 3.0 release: GDNative allows scripting in C++ without needing to recompile (or even restart) Godot.
最后,我们为3.0发行版增添了最亮眼的功能之一:GDNative允许使用C ++编写脚本,而无需重新编译(甚至重新启动)Godot。 Any C++ version can be used, and mixing compiler brands and versions for the generated shared libraries works perfectly, thanks to our use of an internal C API Bridge.
可以使用任何C ++版本,并且由于我们使用了内部C API Bridge,因此可以将生成器共享库的编译器品牌和版本完美地结合在一起。 This language is the best choice for performance and does not need to be used throughout an entire game, as other parts can be written in GDScript or Visual Script. However, the API is clear and easy to use as it resembles, mostly, Godot's actual C++ API.
该语言是提高性能的最佳选择,并且不需要在整个游戏中使用,因为其他部分可以用GDScript或Visual Script编写。但是,该API清晰易用,因为它与Godot的实际C ++ API非常相似。 More languages can be made available through the GDNative interface, but keep in mind we don't have official support for them.
您可以通过GDNative界面提供更多语言,但是请记住,我们没有官方语言支持。
Scripting a sceneFor the rest of this tutorial we'll set up a GUI scene consisting of a button and a label, where pressing the button will update the label. This will demonstrate:
在本教程的其余部分中,我们将设置一个由按钮和标签组成的GUI场景,按此按钮将更新标签。这将表明 - Writing a script and attaching it to a node.编写脚本并将其附加到节点。
- Hooking up UI elements via signals.通过信号连接UI元素。
- Writing a script that can access other nodes in the scene.编写可以访问场景中其他节点的脚本。
Before continuing, please make sure to read the GDScript reference. It's a language designed to be simple, and the reference is short, so it will not take more than a few minutes to get an overview of the concepts.
在继续之前,请确保阅读GDScript参考。这是一种设计简单的语言,参考文献很短,因此大致了解概念不会花费几分钟。 Scene setup
场景设定Use the "Add Child Node" dialogue accessed from the Scene tab (or by pressing Ctrl + A) to create a hierarchy with the following nodes:
使用从“场景”选项卡访问的“添加子节点”对话框(或通过按Ctrl + A)来创建具有以下节点的层次结构: The scene tree should look like this:
场景树应如下所示: Use the 2D editor to position and resize the Button and Label so that they look like the image below. You can set the text from the Inspector tab.
使用2D编辑器定位“按钮”和“标签”并调整其大小,以使其看起来像下面的图像。您可以从“检查器”选项卡设置文本。 Finally, save the scene with a name such as sayhello.tscn.
最后,使用诸如这样的名称保存场景sayhello.tscn。
Adding a script
添加脚本Right click on the Panel node, then select "Attach Script" from the context menu:
右键单击“面板”节点,然后从上下文菜单中选择“附加脚本”: The script creation dialog will pop up. This dialog allows you to set the script's language, class name, and other relevant options.
脚本创建对话框将弹出。该对话框允许您设置脚本的语言,类名和其他相关选项。 In GDScript, the file itself represents the class, so the class name field is not editable.
在GDScript中,文件本身代表类,因此类名称字段不可编辑。 The node we're attaching the script to is a panel, so the Inherits field will automatically be filled in with "Panel". This is what we want, as the script's goal is to extend the functionality of our panel node.
我们将脚本附加到的节点是一个面板,因此“继承”字段将自动用“ Panel”填充。这就是我们想要的,因为脚本的目标是扩展面板节点的功能。 Finally, enter a path name for the script and select Create:
最后,输入脚本的路径名称,然后选择创建: The script will then be created and added to the node. You can see this as an "Open script" icon next to the node in the Scene tab, as well as in the script property under Inspector:
然后将创建脚本并将其添加到节点。您可以在“场景”选项卡中的节点旁边以及“检查器”下的脚本属性中,将其视为“打开脚本”图标。 To edit the script, select either of these buttons, both of which are highlighted in the above image. This will bring you to the script editor, where a default template will be included:
要编辑脚本,请选择这两个按钮中的一个,在上图中将两个按钮都突出显示。这将带您进入脚本编辑器,其中将包含默认模板: There's not much there. The _ready() function is called when the node, and all its children, enters the active scene. Note: _ready() is not the constructor; the constructor is instead _init().
那里没有很多。_ready()当节点及其所有子节点进入活动场景时,将调用该函数。注意: _ready()不是构造函数;构造函数是_init()。
The role of the script
脚本的作用A script adds behavior to a node. It is used to control how the node functions as well as how it interacts with other nodes: children, parent, siblings, and so on. The local scope of the script is the node. In other words, the script inherits the functions provided by that node.
脚本将行为添加到节点。它用于控制节点的功能以及与其他节点的交互方式:子节点,父节点,兄弟姐妹等。脚本的本地作用域是节点。换句话说,脚本继承了该节点提供的功能。
Handling a signal
处理机制Signals are "emitted" when some specific kind of action happens, and they can be connected to any function of any script instance. Signals are used mostly in GUI nodes, although other nodes have them too, and you can even define custom signals in your own scripts.
当发生某种特定类型的动作时,信号被“发出”,并且它们可以连接到任何脚本实例的任何功能。信号主要用于GUI节点,尽管其他节点也有信号,您甚至可以在自己的脚本中定义自定义信号。 In this step, we'll connect the "pressed" signal to a custom function. Forming connections is the first part and defining the custom function is the second part. For the first part, Godot provides two ways to create connections: through a visual interface the editor provides or through code.
在此步骤中,我们将“按下”信号连接到自定义功能。形成连接是第一部分,定义自定义功能是第二部分。对于第一部分,Godot提供了两种创建连接的方式:通过编辑器提供的可视界面或通过代码。 While we will use the code method for the remainder of this tutorial series, let's cover how the editor interface works for future reference.
尽管在本系列教程的其余部分中将使用code方法,但让我们介绍一下编辑器界面的工作方式以供将来参考。 Select the Button node in the scene tree and then select the "Node" tab. Next, make sure that you have "Signals" selected.
在场景树中选择“按钮”节点,然后选择“节点”选项卡。接下来,确保已选择“信号”。 If you then select "pressed()" under "BaseButton" and click the "Connect..." button in the bottom right, you'll open up the connection creation dialogue.
如果然后在“ BaseButton”下选择“ pressed()”并单击右下角的“ Connect ...”按钮,则将打开连接创建对话框。 The top of the dialogue displays a list of your scene's nodes with the emitting node's name highlighted in blue. Select the "Panel" node here.
对话框顶部显示场景节点的列表,其中发射节点的名称以蓝色突出显示。在此处选择“面板”节点。 The bottom of the dialogue shows the name of the method that will be created. By default, the method name will contain the emitting node's name ("Button" in this case), resulting in _on_[EmitterNode]_[signal_name].
对话框的底部显示了将要创建的方法的名称。默认情况下,方法名称将包含发射节点的名称(在本例中为“ Button”),结果为_on_[EmitterNode]_[signal_name]。 And that concludes the guide on how to use the visual interface. However, this is a scripting tutorial, so for the sake of learning, let's dive into the manual process!
到此,您就可以得出有关如何使用可视界面的指南。但是,这是一个脚本教程,因此,为了学习起见,让我们深入研究手动过程! To accomplish this, we will introduce a function that is probably the most used by Godot programmers: Node.get_node(). This function uses paths to fetch nodes anywhere in the scene, relative to the node that owns the script.
为此,我们将介绍一个可能是Godot程序员最常使用的函数:Node.get_node()。此函数使用路径来获取场景中相对于拥有脚本的节点的节点。 For the sake of convenience, delete everything underneath extends Panel. You will fill out the rest of the script manually.
为了方便起见,请删除下面的所有内容。您将手动填写其余脚本。extends Panel Because the Button and Label are siblings under the Panel where the script is attached, you can fetch the Button by typing the following underneath the _ready() function:
由于Button和Label是在附加脚本的面板下的兄弟姐妹,因此可以通过在_ready()函数下方键入以下内容来获取Button :
GDScript
- <span class="k" style="box-sizing: border-box; color: var(--highlight-keyword-color); font-weight: bold;">func</span> <span class="n" style="box-sizing: border-box;">_ready</span><span class="p" style="box-sizing: border-box;">():</span>
- <span class="n" style="box-sizing: border-box;">get_node</span><span class="p" style="box-sizing: border-box;">(</span><span class="s2" style="box-sizing: border-box; color: var(--highlight-string-color);">"Button"</span><span class="p" style="box-sizing: border-box;">)</span>
复制代码 C#- public override void _Ready()
- {
- GetNode("Button");
- }
复制代码 Next, write a function which will be called when the button is pressed:
接下来,编写一个在按下按钮时将被调用的函数:
GDScript
- func _on_Button_pressed():
- get_node("Label").text = "HELLO!"
复制代码 C#- public void _OnButtonPressed()
- {
- GetNode<Label>("Label").Text = "HELLO!";
- }
复制代码
Finally, connect the button's "pressed" signal to _on_Button_pressed() by using Object.connect().
最后,_on_Button_pressed()使用Object.connect()将按钮的“按下”信号连接到。
GDScript
- func _ready():
- get_node("Button").connect("pressed", self, "_on_Button_pressed")
复制代码 C#- public override void _Ready()
- {
- GetNode("Button").Connect("pressed", this, nameof(_OnButtonPressed));
- }
复制代码 The final script should look like this:
最终脚本应如下所示:
GDScript- extends Panel
- func _ready():
- get_node("Button").connect("pressed", self, "_on_Button_pressed")
- func _on_Button_pressed():
- get_node("Label").text = "HELLO!"
复制代码 C#- using Godot;
- // IMPORTANT: the name of the class MUST match the filename exactly.
- // this is case sensitive!
- public class sayhello : Panel
- {
- public override void _Ready()
- {
- GetNode("Button").Connect("pressed", this, nameof(_OnButtonPressed));
- }
- public void _OnButtonPressed()
- {
- GetNode<Label>("Label").Text = "HELLO!";
- }
- }
复制代码 Run the scene and press the button. You should get the following result:
运行场景并按按钮。您应该得到以下结果:
Why, hello there! Congratulations on scripting your first scene.
为什么,你好!恭喜您编写了第一个场景脚本。
A common misunderstanding regarding this tutorial is how get_node(path) works. For a given node, get_node(path) searches its immediate children. In the above code, this means that Button must be a child of Panel. If Button were instead a child of Label, the code to obtain it would be:
关于本教程的一个常见误解是get_node(path) 工作方式。对于给定的节点,get_node(path)搜索其直接子节点。在上面的代码中,这意味着Button必须是Panel的子级。如果Button是Label的子代,则获取它的代码将是: GDScript
- # Not for this case,
- # but just in case.
- get_node("Label/Button")
复制代码 C#- // Not for this case,
- // but just in case.
- GetNode("Label/Button")
复制代码 Also, remember that nodes are referenced by name, not by type.
另外,请记住,节点是通过名称而不是类型来引用的。
The 'advanced' panel of the connect dialogue is for binding specific values to the connected function's parameters. You can add and remove values of different types.
连接对话框的“高级”面板用于将特定值绑定到所连接功能的参数。您可以添加和删除不同类型的值。
The code approach also enables this with a 4th Array parameter that is empty by default. Feel free to read up on the Object.connect method for more information.
代码方法还使用Array默认为空的第4个参数启用此功能。随时阅读该Object.connect 方法以获取更多信息。
|