Unity 3D\2D手机游戏开发:从学习到产品(第3版)
上QQ阅读APP看书,第一时间看更新

2.13 精确的碰撞检测

在前面的制作过程中,飞机与子弹之间的碰撞都是使用比较简单的Box碰撞检测,但实际飞机和子弹的形状都比较复杂,这种检测结果会显得很不精确,看上去就像是子弹还没碰到飞机,但已经打中了。

为了能得到更加准确的碰撞检测,可以直接使用模型本身进行碰撞检测,但因为模型的多边形数量较高,对游戏性能会产生很大影响。比较好的做法是使用一个与模型形状近似的碰撞模型,但尽可能简单,专门用来检测碰撞,具体步骤如下:

步骤 01 使用3D软件,比如3ds Max或Maya,为游戏中使用的模型Enemy2创建一个碰撞模型,如图2-53所示。注意,这个工作通常是由3D美术工作者来完成。

图2-53 为Enemy2创建碰撞模型

步骤 02 为碰撞模型命名,这里命名为col,同时选中游戏模型和碰撞模型,将它们一起导出为FBX文件,命名为Enemy2b,然后导入到Unity中。

步骤 03 参考本章前面的内容,为Enemy2b制作为敌人的Prefab。注意,它有两个子物体;一个名为col,即是碰撞模型;另一个才是游戏中显示的模型。选择碰撞模型,在菜单栏中选择【Component】→【Physics】→【Mesh Collider】,为它添加一个Mesh碰撞体。因为我们在游戏中并不想看到碰撞模型,所以将【Mesh Renderer】取消选中,如图2-54所示。

图2-54 设置Prefab

在Enemy.cs的Start函数中,原来是通过this.GetComponent<Renderer>()语句获得模型的Renderer(渲染器),但Enemy2b的Renderer在游戏体的子一级,所以this.GetComponent会返回空值。有很多种方式可以获得子一级的Renderer组件,比如将m_renderer变量设为public,手动指定Renderer,或者使用this.transform.find函数,使用this.GetComponentInChildren函数都可以获得子一级游戏体组件。这里我们将单独为带有Renderer的模型创建一个脚本。

步骤 04 创建脚本EnemyRenderer.cs,注意变量m_isActiv和m_renderer都是internal类型的。

        public class EnemyRenderer : MonoBehaviour {

            public Enemy m_enemy;
        void Start () {
              m_enemy=this.GetComponentInParent<Enemy>();  // 获得Enemy脚本
            }

            void OnBecameVisible()  // 当模型进入屏幕
            {
                m_enemy.m_isActiv=true;  // 更新Enemy脚本状态
                m_enemy.m_renderer =this.GetComponent<Renderer>();  // 使Enemy获得Renderer
            }
        }

步骤 05 将EnemyRenderer.cs指定给Enemy2b层级下的enemy2,如图2-55所示。

图2-55 指定脚本

将Enemy2b的Prefab放入游戏中,会发现碰撞更加精准了。