文章目录
- 前言
- 场景搭建
- 新建子场景
- 最简单的按钮事件
- 手动控制场景
- 手动加载场景
- 添加多个场景对象
- 更快速的获取脚本对象
- 删除多个场景对象
- 脚本命名的问题
- 总结
前言
Godot的场景是C#与Godot最后的中间连接。我们解决了场景的加载,我们基本可以保证C#和godot之间的彻底分离。
场景搭建
新建子场景
我们新建一个最简单的子场景,我们按照规范,应该只在Node 2D的节点上面添加子场景。
场景新建原则:
- 根节点必须是Node 2D节点,因为Node 2D节点是最优的通用节点
- 只在根节点上面添加唯一的脚本
在 Godot 中应用面向对象原则
最简单的按钮事件
public partial class TestSence:Godot.Node2D
{
private Button button;
private int num = 0;
public TestSence() {
}
public override void _Ready()
{
button = GetNode<Button>("Button");
button.ButtonDown += () =>
{
button.Text = $"按钮 {num}";
num++;
};
base._Ready();
}
public override void _Process(double delta)
{
base._Process(delta);
}
}
手动控制场景
Godot Engine 4.2 简体中文文档 最佳实践 场景组织
手动加载场景
Godot Engine 4.2 简体中文文档 最佳实践 何时使用场景与脚本
主场景的脚本事件
namespace Test2.SenceScripts
{
public partial class MainSence : Godot.Node2D
{
public MainSence() { }
public override void _Ready()
{
//加载脚本
var packedScene = ResourceLoader.Load<PackedScene>("res://Sences//Test.tscn").Instantiate();
//自动添加在子节点上面
AddChild(packedScene);
}
public override void _Process(double delta)
{
base._Process(delta);
}
}
}
添加多个场景对象
public override void _Ready()
{
//加载脚本
var packedScene = ResourceLoader.Load<PackedScene>("res://Sences//Test.tscn").Instantiate();
//无法添加多个脚本,因为会出现命名冲突
for(var i = 0; i < 10; i++)
{
//自动添加在子节点上面
AddChild(packedScene);
}
}
正确示范
public override void _Ready()
{
//加载脚本
var packedScene = ResourceLoader.Load<PackedScene>("res://Sences//Test.tscn");
for (var i = 0; i < 10; i++)
{
//每次都要重新创建
var newPackedScene = packedScene.Instantiate();
//给每个都赋值不同的名字,保证不会出现冲突
newPackedScene.Name = "Test" + i;
AddChild(newPackedScene);
//反向获取脚本对象
TestSence testSence = GetNode<TestSence>(newPackedScene.Name.ToString());
//通过修改节点的位置防止重叠
testSence.Position = new Vector2(i * 100, 0);
//if (i < 5)
// RemoveChild(packedScene);
}
GD.Print("我已经实例化了");
base._Ready();
}
更快速的获取脚本对象
var newPackedScene = packedScene.Instantiate();
//给每个都赋值不同的名字,保证不会出现冲突
newPackedScene.Name = "Test" + i;
AddChild(newPackedScene);
//反向获取脚本对象
TestSence testSence = GetNode<TestSence>(newPackedScene.Name.ToString());
这个添加之后再获取脚本对象太过于麻烦,我们可以通过泛型来获取,这样就少了一个反向获取的操作
var newPackedScene = packedScene.Instantiate<TestSence>();
//给每个都赋值不同的名字,保证不会出现冲突
newPackedScene.Name = "Test" + i;
AddChild(newPackedScene);
删除多个场景对象
for (var i = 0; i < 10; i++)
{
//每次都要重新创建
var newPackedScene = packedScene.Instantiate();
//给每个都赋值不同的名字,保证不会出现冲突
newPackedScene.Name = "Test" + i;
AddChild(newPackedScene);
//反向获取脚本对象
TestSence testSence = GetNode<TestSence>(newPackedScene.Name.ToString());
//通过修改节点的位置防止重叠
testSence.Position = new Vector2(i * 100, 0);
//将前五个移出
if (i < 5)
RemoveChild(newPackedScene);
}
GD.Print("我已经实例化了");
base._Ready();
}
脚本命名的问题
总结
官方文档写的特别好,建议大家按照官方文档的最佳实践编写Godot代码。