在其他实例中处理变量

在专门讨论变量的章节中,你发现了如何在单个实例中或在全局范围内创建和使用变量,但如果你想让一个实例访问另一个不同实例中的变量,会发生什么?有很多情况下你可能想这样做,例如在与子弹物体的碰撞中,你可能想通过访问子弹中的一个变量来了解子弹的伤害程度,或者你可能想在一个谜题中停止所有球的运动,或者你可能想把主角移动到一个特定的位置,或者你在任何游戏中通常遇到的任何其他情况。值得庆幸的是,GameMaker语言配备了实现这一目的的机制。

另一个实例中访问或更改变量的最常见方法之一是使用其对象名称作为标识符,然后使用点.告诉GameMaker该变量是引用应该在该特定对象的实例中分配或更改。这称为"点表示法",其语法如下:

<object_id>.<variable> = <value>; 

在实践中,它看起来像这样。

obj_ball.speed = 0;

通过上述代码,您可以设置obj_ball实例的速度。不过,如果房间中有多个给定对象的实例,那么它将同等地应用于所有实例- 除非您使用HTML5,在这种情况下,它将仅影响一个,但您无法知道它会影响哪一个 - 因此,如果您需要访问某个对象的所有实例,您应该使用with,因为这是 100% 跨平台的兼容的。一般来说,只有当您在房间中只有一个对象实例时,或者(正如您将在下一部分中看到的)当您有特定的实例ID时,才应使用此格式。

当房间内有多个实例时,您还可以使用唯一的实例名称来访问对象的单个实例,以准确告知GameMaker我们希望访问哪个实例。实例名称常量是为添加到游戏房间中的每个实例指定的唯一标识常量。您可以通过双击房间编辑器中的实例来找到该常量:

The instance constant in the room editor请注意,可以编辑此名称并赋予更描述性的名称-尽管名称必须对于整个游戏而言是唯一的-并且可以用作点的左侧:

inst_4DB70D2.speed = 0;

注意在游戏中,此名称是实例的句柄。请参阅数据类型了解更多信息。

然而,到目前为止,最常见和实用的方法是在点左侧使用变量,只要有问题的变量存储了有效的实例id。下面的例子说明了这一点。

// Example 1
var _inst = instance_position(mouse_x, mouse_y, all);
if (instance_exists(_inst))
{
    _inst.speed = 0;
}

// Example 2
var _inst = instance_create_layer(mouse_x, mouse_y, "Enemies", obj_E_Parent);
_inst.direction = point_direction(_inst.x, _inst.y, x, y);
_inst.target = id;

在上面示例 1 的代码中,代码块中有一个instance_exists调用。这是因为,如果该实例不存在,使用 point 方法访问或更改另一个实例值将给出错误并导致游戏崩溃,并且该示例中可能存在这种情况。然而,在示例 2 和 3 中,我们不需要进行检查,因为我们知道该实例存在,因为在示例 2 中我们创建了该实例,而在示例 3 中,它是碰撞事件中的另一个实例。但是,如果在使用此方法时存在实例被销毁、停用或以其他方式从房间中移除的任何可能性,您应该始终使用instance_exists函数或instance_number函数。

请注意,您不能在此方法中使用特殊的 关键字 all 来定位所有实例 (例如:all.val = 10; 会给出错误),但您 可以 使用关键字 otherself 不会出现问题。例如,在 碰撞事件 中使用 other

// Example 3 other.hp -= 10;
if (other.hp <= 0)
{
    other.sprite_index = spr_E_Dead;
}

同样重要的是要注意,你不能使用任何函数本身作为赋值的左边。例如,下面的代码会给你一个错误。

instance_nearest(x, y, obj).speed = 0;

该代码示例中表达式的返回值是一个整数(最近实例的唯一 ID 值),因此必须将其括在方括号( )中才能以这种方式使用并正确寻址所需的实例。上面的代码可以正确写为:

(instance_nearest(x, y, obj)).speed = 0;

//or

var _inst = instance_nearest(x, y, obj);
_inst.speed = 0;

这些都是在其他实例中读取、更改和设置变量的完全有效的方法,并且之所以有效,是因为该点实际上是一个运算符。它采用一个值作为左操作数,一个变量作为右操作数,并返回指定对象或实例中该特定变量的地址。所有对象名称、常量、ID 等都简单地表示值,并且可以像处理任何其他值一样处理这些值。

在另一个实例中引用变量的另一种方法是使用 GameMaker 语言语句with

// This will affect all instances of the object "obj_Enemy"
with (obj_Enemy)
{
    target = other.parent;
}

// This will affect one instance of the object "obj_Enemy"
var _enemy = instance_nearest(x, y, obj_Enemy);
if (instance_exists(_enemy))
{
    with (_enemy)
    {
        target.x = mouse_x;
        target.y = mouse_y;
    }
}