父对象

GameMaker IDE 中处理对象时,您可以设置父对象/子对象层次。要实现这一点,可以在对象编辑器中单击"父对象"按钮,然后从资源浏览器中选择另一个对象作为正在编辑的对象的"父对象":

Adding A Parent所以,游戏项目中的每个对象都可以有一个父对象,但这意味着什么?当一个对象被分配了父对象时,它可以与该父对象共享代码、操作和事件。这种共享称为“继承”,具有父对象的对象称为“子”对象。子对象不仅可以与其父对象共享代码,还可以对父对象进行检查和运行代码,它也会自动包含子对象,这节省了大量的时间和精力。

如果这听起来很复杂,那么看待父对象的另一种方式是将对象“分组”到同一把伞下,让它们共享某些东西,而不会失去自己的独特身份。也许这还不能把事情说清楚,所以让我们举几个例子。

假设你有一个"玩家"对象和四个不同的"敌人"对象。现在,如果玩家接触到这四个物体中的任何一个,你就会想要他死掉,这通常会导致四个不同的碰撞事件和四组不同的动作或代码,每个敌人物体一个。但如果我们为所有敌人制作一个父对象,那么我们只能创建一个与父对象的碰撞事件,并且无论四个"子"敌人对象中的哪一个接触到玩家,它都会触发。方便的东西!在实际的 GameMaker 对象中,您将看到如下所示:

Parenting For Collisions左边有四个独立的碰撞事件,右边有一个碰撞事件,因为我们已经创建了一个"父"对象,并将所有敌人对象分配给了它。请注意,父对象不一定要包含任何事件或代码...

另一个为人父母的例子是,如果你有一个游戏,你想要创建 10 个看起来不同的对象,并让它们以相同的方式运行。为此,您将创建一个父对象,并在其中将所有行为动作或代码放在所需的事件中,然后您将创建十个没有动作或代码但具有不同精灵的对象,并将它们分配给您的父对象。现在,当您将这些实例放置在一个房间中时,它们的行为都相同,但外观不同,因为它们将"继承"父对象的事件。

最后,你可以用养育方式来"混合搭配"事件和行为。我们将用最后一个例子来说明这一点。假设你想要两个怪物:一个上下移动,另一个左右移动,但你也希望这两个怪物有相同的健康,向玩家射击,并在他们相撞时伤害玩家。在这种情况下,您可以看到,除了一两个控制运动的事件之外,几乎所有的事件都应该有相同的动作。因此,同样,我们可以使一个对象成为另一个对象的父对象,但在本例中,我们还为子对象定义了某些事件。这些事件"覆盖"父事件,这意味着只要子对象的事件包含操作,就会执行这些操作,而不是执行父对象的事件中包含的操作。如果您还想执行父事件,则可以使用函数event_inherited()或 GML 可视化操作调用父事件来调用所谓的"继承"事件。

Inheriting Events在上面的左边是父对象,其中有5个事件,在右边你可以看到"子"对象。子对象中也有5个事件,但其中两个覆盖了从父对象继承的事件(步骤绘制事件),另外三个是灰色的,因为它们是从父对象继承的事件。在事件编辑器中,继承的事件旁边还会有"父覆盖"图标:

Parent Override当您在已继承的事件上单击LMB Icon时,它将打开代码编辑器以显示继承的父代码,但您将无法编辑此代码,因为您只能在父对象本身中编辑它。您可以在任何父事件上单击鼠标右键RMB Icon以打开以下选项菜单:

Parent Event RMB Menu您可以在此处选择两个开启父事件来检查代码,也可以选择继承该事件或重写该事件。如果选择继承,则代码编辑器将打开,其中包含已添加到其中的函数 event_inherited() (如果使用 GML 可视化,则为调用父事件操作)。现在,您放置在此事件中的任何进一步代码都将与父对象拥有的代码一样运行。如果您选择重写事件,则代码窗口也将打开,只是现在不会调用 event_inherited() 函数,因此您在此处添加的任何内容都将运行不是父对象中的代码。

注意:从代码编辑器中,您可以通过单击鼠标右键RMB Icon并从弹出菜单中选择转到对象来快速导航到父对象,或者(如果事件已被覆盖)您可以选择打开继承的事件以直接转到包含父事件代码的代码编辑器。

每当您在代码中以父对象为目标时,代码也将应用于父对象的"子对象"。当您在操作中指示该操作必须应用于某个对象的实例,并且在代码中使用 with() 语句时,就会发生这种情况。当您调用代码函数时,它也会这样工作,如 instance_position()instance_number() 等 ...。其中-如果您提供父对象-父 子实例的所有实例都将包括在检查中。最后,当你引用其他对象中的变量时,父子关系也会起作用,比如在上面的怪物例子中,如果我将敌人 1 的速度设置为 10,那么敌人 2 的速度也会变成 10,因为它是敌人 1 的子对象。

在大多数情况下,创建一个基父对象并让这个基对象包含所有默认行为,但从不在游戏中使用它的实例,这通常被认为是很好的做法。而是使用所有子对象,仅在我上面概述的情况下使用父对象,用于冲突、引用变量等。你也应该意识到,父母也可以有父母!显然,您不能创建 "parent1 是 parent2 的子代 " 的循环,但可以创建所谓的 "对象层次结构",其中 "parent3parent2 的子代parent1 的子代"。这对保持您的游戏结构非常有用,强烈建议您学习使用此机制。