Programming Guide/zh

From Space Engineers Wiki
Jump to: navigation, search

在太空工程师游戏内编程是通过可编程块完成的,可以使用C#(念做 C Sharp)语言来编写脚本。 它可用于制造自主式采矿无人机,远距离玩家捕杀鱼雷,船舶建造用自动焊接臂等等。

介绍

编辑权限

同一时间只有一个玩家可以编辑同一个脚本。 如果已经有一个人在当前块打开编辑器,而此时其他人试图打开该块的编辑器时,会显示一条通知,表示编辑器已经打开。

Main 方法

当编辑器第一次打开时,代码编辑器中会出现void Main() 方法。
这是执行脚本时程序调用的入口方法。 如果删除/重命名Main方法,脚本将不会运行,您将在可编程块详细信息区域中收到通知。
可以定义和使用自定义方法/变量,但只调用Main方法而不引用。

变量的生命周期

脚本中有两种类型的变量:
局部变量(定义在方法内部) - 这些变量仅在方法被执行期间保持其值。方法结束时,变量值将“丢失”。
全局变量(定义在方法外部) - 这些变量将在整个脚本的生命周期内保持其值。
例如:如果变量需要在程序运行时保持值,则需要在方法之外定义它。
按“保存并退出”或“保存”按钮后,之前的脚本将被覆盖,之前所有的全局变量都将丢失。
除了内置的保留变量之外的所有变量(局部和全局变量)将在重新编译代码时以及在已保存的游戏加载之间丢失其值或返回其默认值。
保留变量的独特之处在于它可以将在保存中和重新编译时的数据存储为字符串。

编译

按下“检查代码”按钮时,将编译代码并显示编译结果。
编译过程分为两步:
首先,编辑器内部的代码由c#编译器编译,检查语言错误。
如果在编译期间出现任何错误,则显示以下对话框:
It this case “aaa” string is placed before Main method. This is the wrong language construction and the compilation failed.
(大意为:“aaa”字符串不能放在了Main方法之前。 编译失败。)
在错误对话框中,将显示错误行号和错误描述。

编译后,将检查代码是否使用不允许的命名空间和类型。 如果检查失败,
显示以下对话框:
In this case System.IO.Directory was used to delete some directory. This is forbidden and error is shown that “Not allowed type was used in script”.
(大意为:禁止使用System.IO.Directory删除某个目录。 错误“脚本中使用了不允许的类型”。)

如果编译和检查通过,则会显示一个对话框,确认已通过检查,并保存代码。

脚本执行

按下“运行”按钮或将“运行”指定为终端操作时,将执行脚本。 目前需要手动调用“运行”,例如 用户需要单击“运行”按钮或将其作为终端操作附加。
脚本仅在服务器上执行,即使它是从客户端触发的。 如果在脚本执行期间出现任何异常,将在可编程块详细信息区域中通知所有客户端有关失败的信息。
如果在脚本执行期间发生异常,除非用户打开编辑器并更改脚本,否则脚本将不会再次运行。
计时器还可以通过运行操作(可能会提示您输入参数)继续运行脚本,然后启动/触发自身或通过脚本代码启动/触发(如果脚本崩溃,计时器将停止)。

指令计数

每次执行脚本时,都会计算脚本的每条指令。 如果脚本执行的指令多于限制,则停止执行并通知用户脚本太复杂而无法执行。 这可以防止脚本“冻结”游戏。

白名单

脚本中允许的类型和类受到限制。 请参阅脚本白名单以查看允许使用的内容。

可用的接口

可用的操作

目前,只能在脚本内触发终端操作。 用户可以访问可编程块所在的网格的终端系统,并触发网格上任何块的任何终端动作。

方块类 (操作对象列表)

同一方块类的不同SubTypeID

一些块具有相同的父类 (例如: 在 cubeblocks.sbc中的<TypeId> ) 只有子类不同 (例如:其中的<SubtypeId>). 这意味着代码中的这些块之间没有区别。
一个例子是货物储存箱:在游戏中有三种货物储存箱:小型、中型和大型。这三种类型的区别仅在于子类型不同。
例如:大型货物储存箱的id是:
<Id>
<TypeId>CargoContainer</TypeId>
<SubtypeId>LargeBlockLargeContainer</SubtypeId>
</Id>
中型的是:
<Id>
<TypeId>CargoContainer</TypeId>
<SubtypeId>SmallBlockMediumContainer</SubtypeId>
</Id>
小型的是:
<Id>
<TypeId>CargoContainer</TypeId>
<SubtypeId>LargeBlockSmallContainer</SubtypeId>
</Id>

在这种情况下,所有类型的货物储存箱都只有一个类IMyCargoContainer。

示例程序

Hello world

Space Engineers中的标准Hello World程序可以这样编写:

public void Main()
{
   Echo ("Hello, world!");
}

如果将该程序输入可编程块并运行,将导致“Hello,world!” 显示在屏幕右下方的可编程块界面中。

获得你的位置

该程序将显示编程块在世界中的位置的当前GPS坐标。

public void Main()
{
    var pos = Me.GetPosition();
    Echo (pos.ToString());
}


检查传感器

如果您只是将该操作放在传感器的“设置操作”列表中,即使没有任何编程,也很容易让传感器打开门或触发其他操作。 但是,当传感器“没有”检测到某些东西时触发动作将变得困难,并且无法通过定时器块完成。 该程序将每10个游戏周期自动检查一个传感器(每秒工作约6次),如果传感器没有检测到任何东西,则关闭一个门。 这可以很容易地应用于其他目的,例如当小行星不在传感器范围内时关闭钻头。

List<MyDetectedEntityInfo> entity_list = new List<MyDetectedEntityInfo>(); 
public Program()
{
    Runtime.UpdateFrequency = UpdateFrequency.Update10;
    //This makes the program automatically run every 10 ticks.
}
public void Main()
{
    var door_sensor = GridTerminalSystem.GetBlockWithName("Door Sensor 1") as IMySensorBlock;
    door_sensor.DetectedEntities (entity_list);
    if (entity_list.Count == 0)
    {
        var door = GridTerminalSystem.GetBlockWithName("Door 1") as IMyDoor;
        door.ApplyAction ("Open_Off");
    }
}

要使此脚本起作用,传感器必须命名为“Door Sensor 1”,门必须命名为“Door 1”。 如果您将传感器配置为打开门,则当玩家进入传感器范围时门将自动打开,当玩家离开传感器范围时门将关闭。

编译错误

这是已知编译错误的列表(正在进行中)以及导致它们的原因。

  • Method name expected: 编译器在不期望它们时找到括号。 您可能在括号前缺少方法名称,或者您可能不恰当地使用括号而不是方括号或大括号,具体取决于您要执行的操作。

另请参见

  • MyGridTerminalSystem - Methods for getting object references to your various ship components.
  • Programming Guide/Action List - Actions you can apply to objects via the Object.ApplyAction method. Also includes some of the object properties. Data appears incomplete as of March 19th, 2018.

外部链接