合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
## 获取方块 我们知道了方块是一个类,那么方块是不是需要通过new方法实例化出来呢? 并不是 当一个方块被放置在游戏场景中的瞬间,游戏的其他代码就已经将这个方块通过new方法实例化出来了。 而我们在编程块中所能做的,只是通过K社提供的几个方法来获取已经存在于场景中的方块。 记住这几点: >[danger] 1.在编程块中,你只能获取已经存在的方块。 >2.由于编程块本身就是一个方块,你只能在编程块中获取与编程块连接的其他方块。(同网格,包括子网格) >**3.当你通过某个方法获取了一个方块,并将它赋值给一个公共变量后。只要这个公共变量没有被重新赋值,并且编程块也没有被初始化。在之后的任何时间,编程块中的这个公共变量都能代表这个方块。** >**** >**这意味着,当你用编程块获取一个方块并赋值给公共变量后,哪怕这个方块脱离了编程块所在网格,并且飞出去无论多远,编程块都可以通过这个公共变量来直接操控这个方块!** > >**这就是我们所说的“纠缠效应”** ### 如何获取方块? K社给了一个类,这个类就相当于编程块本体(大概可以这样理解,可能不准确)。 在编程块中的任何函数中(除了类中),都可以直接使用GridTerminalSystem来访问这个类中的代码。 **编程块有且只有这些方法来获取方块** >[danger] 顺便提一下,在编程块中。“Me”这个单词,代指编程块自己,它的类型是IMyProgrammableBlock。 >你可以在Main函数中试着写 Echo(Me.CustomName.ToString()); 试试 ~~~ namespace Sandbox.ModAPI.Ingame { using System; using System.Collections.Generic; using System.Runtime.InteropServices; public interface IMyGridTerminalSystem { void GetBlockGroups(List<IMyBlockGroup> blockGroups, Func<IMyBlockGroup, bool> collect = null); IMyBlockGroup GetBlockGroupWithName(string name); void GetBlocks(List<IMyTerminalBlock> blocks); void GetBlocksOfType<T>(List<IMyTerminalBlock> blocks, Func<IMyTerminalBlock, bool> collect = null) where T: class; void GetBlocksOfType<T>(List<T> blocks, Func<T, bool> collect = null) where T: class; IMyTerminalBlock GetBlockWithId(long id); IMyTerminalBlock GetBlockWithName(string name); void SearchBlocksOfName(string name, List<IMyTerminalBlock> blocks, Func<IMyTerminalBlock, bool> collect = null); } } ~~~ 光看这些函数的定义,可能不太明白怎么使用。特别是有些void类型的空函数,明明不返回任何值,为什么可以获取到方块,它把获取到的方块放在了哪里? 下面分别举例(这里我只列举两个最常用的): ~~~ //我们通常将方块存为公共变量,这样一方面可以利用纠缠效应,另一方面可以通过一些办法仅在编程块第一帧获取方块,之后就不需要再获取了。 IMyTerminalBlock LCD; List<IMyThrust> Thrusts; void Main(){ //获取单个方块 LCD = GridTerminalSystem.GetBlockWithName("LCD_1"); //获取名字包含LCD_1的单个方块。 //注意,这个方法返回的是IMyTerminalBlock类型。 //子类可以直接使用父类的方法,但父类不能使用子类的,这时候我们想使用IMyTextPanel里的WritePublicText()方法给LCD写入文字怎么办呢? IMyTextPanel LCD_TextPanel_1 = GridTerminalSystem.GetBlockWithName("LCD_1") as IMyTextPanel; //方法1 IMyTextPanel LCD_TextPanel_2 = LCD as IMyTextPanel; //方法2 //可以使用as将父类直接转换成子类,上面这两个写法都是可以的。 //获取多个方块 Thrusts = new List<IMyThrust>(); //记得List结构必须要new以后才可以使用,否则报错 GridTerminalSystem.GetBlocksOfType(Thrusts); //获取到了所有的IMyThrust类型的方块并存入了Thrusts变量中。 //通过条件筛选获取多个方块 Thrusts = new List<IMyThrust>(); //我们重新new了一下Thrust,让它成为一个空List。实际上这里不new也不会报错,因为在GetBlocksOfType方法中,它也会被new一次再赋值的。 GridTerminalSystem.GetBlocksOfType(Thrusts, b => b.CustomName=="MyThrust"); //获取所有类型是IMyThrust并且名字是"MyThrust"的推进器。 /* 这个方法实际上使用了Linq查询,有兴趣可以看Linq部分。如果你只是使用,那么背下来即可 GetBlocksOfType这个方法,必须传入一个参数,并且它使用了out方法,将传入的参数赋值了。 你传入的参数是什么类型,它就会搜索什么类型的方块。 第二个参数可选传入,如果不传入,默认是无条件获取所有该类型方块。如果传入,必须传入一个Linq语句。实际上这里的 b 就代指搜索到的每一个推进器 你也可以用a或者别的,=>是固定写法,=>右侧是一个bool值,相当于判据 如果bool值是true,这个方块就被纳入选择范围,否则不纳入。 不太明白的话,我们再举两个例子 */ List<IMyTerminalBlock> Blocks = new List<IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType(Blocks); //获取所有方块,IMyTerminalBlocks是所有功能方块的基类,记得吗? GridTerminalSystem.GetBlocksOfType(Blocks, b => true); //这一行与上一行等效,因为我们给的bool值被写死成true GridTerminalSystem.GetBlocksOfType(Blocks), b => b.CustomName.Contains("MEA"); //只获取名字包含MEA的方块 GridTerminalSystem.GetBlocksOfType(Blocks, b => b.CustomName.StartsWith("MEA_"));//只获取名字以MEA_头的方块 } ~~~