这将会是你的第一个真正意义上可以控制方块的游戏脚本!
这游戏最常见的应该就是各种门了,我们就写一个可以控制门的脚本,将从 简单 -> 进阶 两部分来讲解
这是最简单的一个脚本,可以做到让一扇门每过一段时间打开/关闭一次。虽然没什么实际作用,但是作为第一段游戏内脚本的理解却是非常合适的。
在开始写我们的代码之前,我们先想一想我们需要什么
既然是一个控制门的脚本,我们第一步首先得 获取门方块,又因为是循环开关门,那就意味着每过一段时间开/关一次,所以我们的第二步就是 统计已过时间,第三步就是如果上次开/关门的时间大于我们设定的时间时(这里我们设定时间为3秒)就 执行一次开/关门。最后循环第二步和第三步即可
那么我们将其列成一个列表大致就是:
2 、3 步有了大体的思路之后,我们就可以进行接下来的操作了。
根据上面的思路,我们首先得放一个门方块

OK,现在我们有一扇门了
光有一个门是不够的我们还得进入终端将 滑动门-hdm- 重新命名为 门 完成了这一步之后,我们就可以进入下一步代码的编写了。
注意:这一步是为了统一你放置的门的名称。因为脚本里面门的名称是写死的,但是玩家放置的门可能会根据门的类型不同而有 不同的名字。
因此,一定要确保刚刚放置的门的名称修改完成,否则脚本将无法获取门方块
我们先来看一下代码,将其复制到你的 Visual Studio 2026 编译器中
using Sandbox.ModAPI.Ingame;
using XFEExtension.SpaceEngineers.ScriptingHelper;
namespace MyProject
{
internal class Program : MyGridProgram, IProgramBase
{
// 注意,复制到游戏内编程块的时候应当从下面开始复制
//------------------从此处开始复制------------------//
// 定义成员变量
private double time; // 定义时间为 double 类型
private IMyDoor myDoor; // 定义门对象为 IMyDoor 接口
public Program()
{
// 这里是 构造函数
time = 0; // 将初始时间设置为0
myDoor = GridTerminalSystem.GetBlockWithName("门") as IMyDoor; // 通过方块的名称获取方块
Runtime.UpdateFrequency = UpdateFrequency.Update10; // 设置 Main函数 触发频率为每10个tick触发一次
}
public void Main(string argument, UpdateType updateSource)
{
// 这里是 主函数
time += Runtime.TimeSinceLastRun.TotalSeconds; // 获取距离上一次 Main函数 被触发过去的时间,以秒为单位
if (time > 3) // 如果累计的已过时间大于3秒
{
time = 0; // 将所有累计的时间情况,等待下一次3秒
if (myDoor.Status == DoorStatus.Closed) // 如果门的状态是关闭的
{
myDoor.OpenDoor(); // 则控制开门
}
else if (myDoor.Status == DoorStatus.Open) // 如果门的状态是开启的
{
myDoor.CloseDoor(); // 则控制关门
}
}
Echo($"已过时间:{time:F2}(s)\n当前门的状态:{myDoor.Status}"); // 输出脚本当前的执行状态,方便我们调试
}
public void Save()
{
// 这里是 保存函数
}
//------------------从此处结束复制------------------//
}
}
乍一看很头疼对吧?那咱们先将其复制到游戏中看看效果
// 定义成员变量
private double time; // 定义时间为 double 类型
private IMyDoor myDoor; // 定义门对象为 IMyDoor 接口
public Program()
{
// 这里是 构造函数
time = 0; // 将初始时间设置为0
myDoor = GridTerminalSystem.GetBlockWithName("门") as IMyDoor; // 通过方块的名称获取方块
Runtime.UpdateFrequency = UpdateFrequency.Update10; // 设置 Main函数 触发频率为每10个tick触发一次
}
public void Main(string argument, UpdateType updateSource)
{
// 这里是 主函数
time += Runtime.TimeSinceLastRun.TotalSeconds; // 获取距离上一次 Main函数 被触发过去的时间,以秒为单位
if (time > 3) // 如果累计的已过时间大于3秒
{
time = 0; // 将所有累计的时间情况,等待下一次3秒
if (myDoor.Status == DoorStatus.Closed) // 如果门的状态是关闭的
{
myDoor.OpenDoor(); // 则控制开门
}
else if (myDoor.Status == DoorStatus.Open) // 如果门的状态是开启的
{
myDoor.CloseDoor(); // 则控制关门
}
}
Echo($"已过时间:{time:F2}(s)\n当前门的状态:{myDoor.Status}"); // 输出脚本当前的执行状态,方便我们调试
}
public void Save()
{
// 这里是 保存函数
}

是不是很神奇,这个门居然会每隔 3s 开/关一次,放恐怖片里面就是妥妥的整蛊道具(666这个门是桂)
那么接下来我们就要开始理解这段代码是在干什么了
现在我们将代码拆开细分成多个部分来讲解:
如果你看了之前的 主要函数介绍 篇就不难发现,我们的讲解顺序其实就是按照:构造函数 > 主函数 > 保存函数 来讲解的,只不过目前我们不需要用到保存函数。
按照先前我们讲的思路——既然我们要 获取门方块,还要 统计已过时间。那么必然的,我们需要存储这两个东西,用什么来存储最合适呢?那当然是变量了!
不过变量和变量之间亦有区别我们这里用的是成员变量,我们先来看看成员变量分的定义吧
定义在 类的内部、方法的外部 的 变量 称为 成员变量 也叫 全局变量
具体对应到我们代码中就是这两行
private double time; // 定义时间为 double 类型
private IMyDoor myDoor; // 定义门对象为 IMyDoor 接口
第一行我们定义了一个 double 双浮点类型的变量用来存储,已过的时间(以秒为单位),第二行 IMyDoor myDoor 用来保存我们通过名字获取到的门对象引用。
下面我们逐段讲解代码是如何工作的。
构造函数在脚本被加载或重编译时执行一次,用来做初始化工作。本例中我们做了三件事:
time 初始化为 0;GridTerminalSystem.GetBlockWithName("门") as IMyDoor 获取名为“门”的方块并转换为 IMyDoor 接口;Runtime.UpdateFrequency = UpdateFrequency.Update10,让 Main 每隔 10 个 tick 被调用一次(注意:不同的世界/服务器 tick 速率不同,这里只是示例)。注意事项:
GetBlockWithName 会返回 null(例如名字不匹配或方块不存在),因此在使用 myDoor 前最好做 null 检查;UpdateFrequency 可以设置为 Update1/Update10/Update100,选择合适频率以平衡响应与性能开销。Main 是脚本的入口,会按设定的频率被触发。关键点如下:
Runtime.TimeSinceLastRun.TotalSeconds 获取距离上一次 Main 被触发经过的秒数,累加到 time;time 超过阈值(例中为 3 秒)时,重置计时并根据门的当前 Status 执行开或关操作:
DoorStatus.Closed 则调用 myDoor.OpenDoor();DoorStatus.Open 则调用 myDoor.CloseDoor();Echo 输出当前状态,便于在可编程块界面调试观察。额外建议:
if (myDoor == null) { Echo("未找到名为 '门' 的方块"); return; } 的判断,避免脚本运行时报错;Opening/Closing 等中间状态,根据需要可以做更细致的处理以避免重复调用。Save 在世界保存时会被调用(例如退出或手动保存),用于将需要持久化的数据写入 Storage。本示例不需要保存数据,因此留空即可。
System.NullReferenceException 之类的报错,请确认方块名称是否正确、方块是否属于同一网格或有权限访问;Echo 输出关键变量,方便在可编程方块界面实时观察脚本行为。Main 的 argument 参数控制(例如传入 interval=5);toggle)时才切换门,而不是循环切换;本教程通过一个简单的循环开关门脚本引导你理解如何获取方块、使用 Runtime 计时、判断方块状态并执行操作。掌握这些基础后,你可以把思路扩展到控制灯光、传送器、转子等更多方块上,构建更复杂的自动化系统。