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

2.12 用鼠标控制主角

目前我们的游戏在PC上运行一切正常,因为手机不方便使用键盘操作,如果移植到手机上便会遇到问题。接下来,我们将为主角增加鼠标操作的功能,当将游戏移植到手机上后,鼠标操作会自动转换为触屏操作。

步骤 01 因为是3D游戏,鼠标的位置只是屏幕坐标,当需要获取到相应的3D坐标时,通常需要一个参照物。我们将创建一个平面并将它放置在与主角飞船Y轴坐标接近的位置作为参照物。在菜单栏中选择【GameObject】→【Create Other】→【Quad】,创建一个平面物体,设置它的位置和大小,使其能铺满整个屏幕,如图2-50所示。

图2-50 设置平面物体

步骤 02 默认的平面物体有一个物理组件【Mesh Collider】,它会使用模型的三角面进行碰撞计算。因为我们只需要平面物体参考位置,并不需要显示它,所以可以取消选中【Mesh Renderer】复选框。

步骤 03 因为场景中有很多物体都有碰撞体,为了区分,这里新建一个层,将平面物体放到这个层中,后面的鼠标操作将产生射线,只与这个层中的平面物体碰撞。先选择Layer,然后选择Add Layer,添加一个名为plane的层,将平面物体的层由Default改为plane,如图2-51所示。

图2-51 设置层

步骤 04 打开脚本Player.cs,添加两个新的属性:一个用于定位主角的目标位置,即鼠标单击的位置;另一个用于设置鼠标射线的碰撞层。

            protected Vector3 m_targetPos; // 目标位置
            public LayerMask m_inputMask; // 鼠标射线碰撞层

步骤 05 在场景中选择主角,将【Input Mask】设置为plane,这样在下面的操作中,鼠标单击产生的射线只与这个plane层内的物体发生碰撞,如图2-52所示。

图2-52 设置层Mask

步骤 06 打开脚本Player.cs,在Start函数中将m_targetPos的值初始化为当前主角的位置,然后添加一个MoveTo函数,代码如下所示:

        void Start () {
              m_transform = this.transform;
              m_audio = this.GetComponent<AudioSource>();
              m_targetPos=this.m_transform.position;  // 添加代码,初始化目标点位置
            }
            void MoveTo()
            {
              if (Input.GetMouseButton(0))
              {
                  Vector3 ms=Input.mousePosition;  // 获得鼠标屏幕位置
                    Ray ray=Camera.main.ScreenPointToRay(ms);  // 将屏幕位置转为射线
                    RaycastHit hitinfo;  // 用来记录射线碰撞信息
                    bool iscast = Physics.Raycast(ray, out hitinfo, 1000, m_inputMask);
                    if (iscast)
                    {
                        // 如果射中目标,记录射线碰撞点
                        m_targetPos = hitinfo.point;
                    }
                }

                // 使用Vector3提供的MoveTowards函数,获得朝目标移动的位置
                Vector3 pos = Vector3.MoveTowards(this.m_transform.position, m_targetPos,
                          m_speed * Time.deltaTime);
                // 更新当前位置
                this.m_transform.position = pos;
              }

使用Input.mousePosition可以获得当前鼠标的屏幕位置,然后使用ScreenPointToRay函数将其转化为一条射线,使用Physics.Raycast函数射出射线,将碰撞结果返回到RaycastHit对象中。Vector3提供了很多种移动、旋转物体的方法,这里使用了它提供的MoveTowards函数,计算出从当前位置朝目标位置移动,返回一个新的位置。

注意,在Physics.Raycast这个函数中,我们引用了m_inputMask参数,射线只会与m_inputMask指定的层中的物体发生碰撞。实际上,我们也可以通过层的名字来指定碰撞层,下面的代码作用与之前是完全一样的,但省去了在编辑器中指定层的步骤,如下所示:

            bool iscast=Physics.Raycast(ray, out hitinfo,1000,  LayerMask.GetMask("plane"); );

最后不要忘记将MoveTo函数放到Update函数中执行。

现在运行游戏,主角将会按鼠标的位置移动,如果将这个游戏移植到手机上,即是按照手指的位置移动。