Unity3D RPG Core | 05 鼠标控制人物移动
这集开始写代码了,首先需要配置一下 Visual Studio(现在还不明白为什么有人喜欢使用 VSCode。除非 VS 没得用,VS 不香么😂),使用 Visual Studio Installer 安装 Unity 开发扩展。不先安装也没有事情,如果没有安装,打开项目的时候也会提示你安装,非常方便。
1. 新建 C# 脚本
首先在 Assets 中,如图 1 所示,新建一个 C# 脚本。这边将其命名为 MouseManager,用于鼠标相关功能的实现。
接着在 Hierarchy 窗体中新建一个空对象用于挂载脚本,视频中让养成好习惯,要将空对象的位置信息重置一下。如图 2 所示,直接把资产中的脚本拖拽到对象查看界面就可以添加。
设置完成之后,我们双击脚本就会自动打开 Unity VS 工程。
2. Unity 事件
代码清单 1 中实现了添加一个 Unity 事件。第 4 行引入事件需要的命名空间 UnityEngine.Events;第 7 行定义一个 Unity 事件,参数是三维向量,因为后续需要传入人物所要移动到的坐标;需要额外添加第 6 行的反序列化特性,这样声明的变量才能显示在 Unity 界面上;第 10 行声明事件变量,命名为 OnMouseClick。
写完如上代码之后,回到 Unity 界面。可以发现,如图 3 所示,脚本处显示出了添加的 OnMouseClick 事件变量。我们将人物对象拖拽其中,指定响应事件的对象;然后设置响应设置事件的变量为 NavMeshAgent.destination(人物的 NavMeshAgent 组件在上一节视频中设置过了)。
设置完后,接下来只需要实现如何触发事件就可以了。
3. 实现鼠标控制人物移动
我们控制人物移动方式是使用 Unity 框架中现成的 NavMeshAgent 组件功能,只要设置其 destination 属性就可以对 Agent 进行移动。
至于如何获取到移动的位置?我们通过从摄像机处引出一条到鼠标点击处的射线,再判断这条射线碰撞到了什么物体。如果是地面,则获取其碰撞的坐标,就是所要移动到的位置。
3.1 Camera.ScreenPointToRay
首先我们来看如何从相机处引出一条射线,它使用 Camera.ScreenPointToRay 函数。
我们可以按照手册上的样例,画一条到 (0, 0) 的射线。(0, 0) 位于屏幕的左下角,所以我们会看到图 4 中的结果。
- Ray ray = Camera.main.ScreenPointToRay(new Vector3(0, 0, 0));
- Debug.DrawRay(ray.origin, ray.direction * 1000, Color.red);
Debug.DrawRay 只能在 Scene 场景中显示,不知道怎么在 Game 场景中显示。
3.2 Physics.Raycast
有了射线,判断射线碰撞到的内容,可以使用 Physics.Raycast 函数,其中一个重载函数原型为:
- bool Raycast(Ray ray, out RaycastHit hitInfo);
返回值返回是否有物体与射线相交。额外返回值 hitInfo,返回具体碰撞信息。具体内容可以参见手册中的 RaycastHit,我们就是通过它来获取碰撞的坐标点。
3.3 开始实现功能
学习了 Camera.ScreenPointToRay 和 Physics.Raycast 的使用之后,就可以开始实现鼠标控制人物移动的功能了。
实现代码如代码清单 2 所示:第 22 行判断是否点击了鼠标左键;如果点击了,就则相机引出一条射线(第 24 行);如果有物体碰撞(第 26 行),则判断碰撞对象是否是地面(第 28 行);如果是地面,则调用之前设置好的 OnMouseClick 事件,其实就是设置 NavMeshAgent.destination,进而控制人物移动。
需要注意的是,这边判断碰撞对象是比较对象的标签,我们需要设置地面物体的标签为 "Ground"。设置的位置如图 5 所示,初始的时候没有名称是 "Ground" 的标签,我们需要添加后再进行选择设置。
3.4 调节 Nav Mesh Agent 参数
至此,移动的功能就已经实现了。但是运行程序后,人物移动看起来有点慢,我们可以调节 Nav Mesh Agent 组件中的现有参数。
如图 6 所示,Nav Mesh Agent 组件中可以设置速度、角速度、加速度、停止距离以及是否有自动刹车效果,我们按照自己想要的效果进行设置即可。
最终的效果如图 7 所示,绑定的动画还是原先素材的循环逻辑,后续需要自己定义。