Unity 3D脚本编程与游戏开发
上QQ阅读APP看书,第一时间看更新

1.2 触发器事件

知道了物体如何移动,下一步就得知道如何判断一个物体是否碰到了另一个物体,这也是绝大部分游戏都需要用到的功能。例如,在经典游戏PONG中,球碰到边界和挡板会反弹;《超级马里奥兄弟》中的马里奥碰到蘑菇就会变大。

实际上,抛开高级游戏引擎提供的各种技术,直接判断物体之间的距离就足以实现碰撞检测,即两个物体之间的距离小于某个值,就是碰到了。早期的游戏就是这么做的,即便在今天,对某些需要特别优化的功能也可以用这种方法。

不过Unity等现代游戏引擎给出了更统一、更简便的方法——使用触发器。

触发器是一个组件,它定义了一个范围。当其他带有碰撞体组件的物体进入了这个范围时,就会产生一个触发事件,脚本捕捉到这个事件的时候,就可以做出相应的处理。

1.2.1 创建触发器

在之前的小球旁边创建一个立方体。创建的立方体已经自带碰撞体,即Box Collider,可以在Inspector窗口中看到,默认该碰撞体的范围就是立方体的范围,如图1-10所示。

55875-00-017-1

图1-10 立方体的Box Collider组件

在Unity中,触发器和碰撞体共用了同一种组件——Collider,实际上两者是不同的概念。勾选Box Collider面板中的Is Trigger选项,碰撞体就变成了同样外形的触发器,如图1-11所示。

55875-00-018-1

图1-11 勾选Box Collider组件的Is Trigger选项

并不是任何物体进入触发器的范围都会产生触发事件。产生触发事件的具体要求将在第3章物理系统中进行讨论。这里需要做的是,给小球添加一个Rigidbody(刚体)组件,并勾选Is Kinematic(动力学)选项,其他选项不重要,如图1-12所示。

55875-00-018-2

图1-12 勾选Rigidbody组件的Is Kinematic选项

做完以上步骤,碰撞的场景设置就完成了,接下来讲解如何编写脚本来处理触发事件。

1.2.2 触发器事件函数

碰撞和触发总是发生在两个物体之间,所以根据不同情况,可以选择其中一个物体进行碰撞或触发的处理。当前按照常规思路,被碰到的物体应该是立方体,因此给立方体新建一个脚本并挂载,取名Coin,用于处理碰撞。

触发事件实际上有3种,即开始触发(OnTriggerEnter)、触发持续中(OnTriggerStay)及结束触发(OnTriggerExit),分别代表另一个物体进入触发范围、在触发范围内、离开触发范围这3个阶段。这里只介绍开始触发事件,Coin脚本内容如下。

using UnityEngine;

public class Coin : MonoBehaviour {
      //  触发开始事件OnTriggerEnter,参数为碰撞体信息,即另一个
进入了该触发区域的物体的碰撞体
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log(other.name + " 碰到了我");
   }
}

小提示

删除不必要的事件函数

可以看到左边代码里不必要的Start()函数、Update()函数等已经通通删除了。这是一种良好的编码习惯,可以减少不必要的函数执行。即使是函数体为空的函数,执行时依然会消耗CPU资源。

以上代码会接收到其他碰撞体进入触发区域的事件,且能获得该碰撞体的信息。上面的代码利用other.name输出了进入触发范围的物体名称。

现在运行游戏进行测试。测试方法是先运行游戏,再直接在场景窗口中拖曳球体,让它和立方体接触,然后观察Console窗口是否出现了消息提示,如图1-13所示。

55875-00-019-1

图1-13 物体接触触发了OnTriggerEnter事件

可以看到,触发时Console窗口输出了消息,而且获得了物体名称Sphere。

1.2.3 实例:吃金币

通过控制物体的运动和触发器,很容易做出游戏中吃金币和金币消失的效果,下面就来实际操作一下。

01 为更好地测试,先在前面例子的基础上调整镜头位置,变成俯视角投。操作方法提示:摄像机位置归0,沿x轴转90°,然后适当沿y轴升高。摄像机的参考位置和旋转角度如图1-14所示。

55875-00-019-2

图1-14 设置俯视角时摄像机的位置和角度

02 新建球体,位置归0。挂载之前用过的Ball脚本,然后添加Rigidbody组件,并勾选Is Kinematic选项,与第1.2.1小节设置相同。

03 新建立方体,位置归0,向右平移摆放到球体旁边。

04 为了让“金币”更醒目,给立方体添加一个金黄色材质。先在Project窗口中新建一个Material(材质),如图1-15所示。

55875-00-019-3

图1-15 创建材质

05 将材质命名为matCoin,如图1-16所示。

55875-00-019-4

图1-16 给材质重命名

06 选中新建的材质,在Inspector窗口中将它的颜色修改为明亮的黄色,如图1-17所示。

55875-00-019-5

图1-17 修改材质的颜色

07 将材质文件直接拖曳到场景中的立方体上,立方体就变成了黄色。这时选中立方体,在Inspector窗口中可以看到材质名称已经变为matCoin了,如图1-18所示。

55875-00-020-1

图1-18 给物体指定材质

完成以上操作后,在Game窗口中看到的效果如图1-19所示。

55875-00-020-2

图1-19 吃金币场景搭建完成

由于球体已挂载了之前的Ball脚本,因此可以根据输入进行移动。注意立方体要勾选Is Trigger选项,并挂载Coin脚本,设置与1.2.1小节相同。

由于金币被碰撞到以后就应该消失,因此修改的Coin脚本如下。

using UnityEngine;

public class Coin : MonoBehaviour {
    // 触发开始事件OnTriggerEnter,参数为碰撞体信息,即另一个进入了该触发区域的物体的碰撞体
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log(other.name + " 碰到了我");
        // 销毁自己
        Destroy(gameObject);
    }
}

此处仅添加了一个Destroy()函数调用,该函数用于销毁物体,而参数gameObject指代的正是脚本所挂载到的物体。如何从物体找到组件,如何从组件找到物体,这些都会在第2章中详细讲解。

测试游戏,用键盘控制小球,检查小球碰到立方体后,立方体是否消失。

如果测试正常,就可以多复制几个立方体。选中立方体,按Ctrl+D快捷键就可以复制立方体,然后调整位置,如图1-20所示。

55875-00-020-3

图1-20 复制多个金币物体并测试

如果读者阅读到了这里,且跟着指引完成了演示案例,那么就能明白编写脚本的基本流程,并理解移动、碰撞等基本操作中每一句代码的含义。如此一来,利用这些知识就能制作一个相对完整的小游戏了。