前言

  由于我们有虚拟现实的课程,需要通过 unity 来实现一个场景漫游效果等等。
  由于我实习了,还没有时间去学习 unity , 汇报也是托了在学校的同学帮忙做前期汇报的。
  所以待我接手开发的时候,那位好心同学给我开了个坑,我需要开发一个类似模拟人生一样的,随意搭配家具的系统。
  当然,其实也没有那么复杂,做出类似的效果就可以了。

最终实现效果

Unity 的准备

  由于不会 Unity ,有需要制作GUI的界面,所以第一步当然是先去找些可用的教程来学习。
  尽管我B站上上传了很多 Pluralsight 相关的 Unity 教程,其实我自己都没怎么看过,一直想学,但是精力有限啊~
  于是终于为了应付作业开始入门学习,入门的话还是先找些国内的教程看看,基础的操作和 Maya 差不多,也没有什么难度。(我还翻译过Unity的入门教程(:з」∠)

  这些就是当初我学习的时候看的教程参考,当然我也没有完全看完,主要挑些有用的重要的部分去看。
  换装系统的部分参考得蛮多的,毕竟比较契合我们想要的实现的效果。
  另外一些零零总总的问题就是通过 Bing 英文搜索解决了, Unity 的官方论坛真的非常有用,遇到问题通常都能在上面找到解决方案。

制作阶段

模型准备

  要搭建场景漫游肯定需要现有一个用于漫游的场景。
  模型下载我是在 cg模型网 上面找免费资源下载进行使用。
  由于前段时间弄 安卓开发 ,我128G的硬盘不够用,所以最后我把很多软件删掉了,其中就包括 3ds Max。
  这次找模型就让我非常痛苦,由于电脑只有 Maya 了,我需要找 Maya 的房屋模型,这就非常难找了。
  最后好不容易找到了一个,虽然房子简陋了点,但是最起码的要求还是达标了。

Maya模型图片

  当然这里还是踩了很多坑,后面需要将有逻辑交互的模型,以及做成 prefab 的模型都要统统在unity分类号,方便后面挂载脚本等的操作。
  另外上的一些缺陷也要在 Maya 里面修补好,比如说Unity基本不支持面片模型,面片的法线是只有正反的,碰撞以及光线穿透都很成问题。
  因此后面我将所有的单面片全部挤出了一丢丢的厚度。
  另外就是墙壁和房间的划分,这部分原模型也没有弄好,因此我做了一些人工的修复。
  还要干掉一些面数过大的模型,原模型的窗帘是用动力学模拟的,为了实现效果,模拟的面数达到 70 多万面,占了整个模型大小的 80 % 以上。
  这些可以通过 减面操作 降低面数。

第一人称控制器

  看千锋教程时候,第一人称控制器是完全从零开始搭建的,这一点让我很诧异,也很膜拜居然可以自己写。
  因为前面做课程的实验,所以我知道 Unity 的官方standard asset 是有做好的第一人称控制器 prefab 的。

Maya模型图片

  实际上,漫游最难的部分其实官方就已经给你准备好了。
  下面就是在官方的基础上配置好相关的碰撞属性即可。

Maya模型图片
Maya模型图片

开门脚本编写

  我最开始实现的就是开门脚本编写。
  其实没有想象中那么复杂,接触了其他语言的代码编写之后,写C#其实本质也差不多。

Maya模型图片

  这里我专门看了 千峰 教程是怎么实现门的开闭。
  虽然教程里面是自动触发的。使用 Vector3.lerp 来实现动画过渡的核心想法还是保留了下来。(其实这里有坑)
  另外使用 public 变量来方便外部调整的 idea 也非常 awesome (运用自如~)
  开门动画就是用程序代码实现的,当然也可以在 Maya 里面制作动画,然后用脚本控制门开合的动画状态。
  不过这个门的开闭其实是非常简单的,根本不需要这么麻烦的实现。


  另外就是要实现靠近门满足特定条件才会触发门开关的效果。
  这里使用了 光线发射器 ,回头一想这就和 three.js 一样的,也是发射光线的碰撞来获取点击。
  然后获取到碰撞的物体之后就可以检测这个物体是否是我们想要的物体,也可以获取到碰撞的距离是多少。
  通过碰撞的检测可以知道这个物体是否是我们想要的模型。
  通过距离的检测不仅可以过滤远程开门,也可以增加一些信息提示。

Maya模型图代码编写片

  setColor 函数就是我封装好的遍历模型下所有的属性进行颜色设置的功能函数
  tip_text 也是下方的gui提示的文本。
  这样就可以实现接触提示的效果。
  Input.GetKeyDown(KeyCode.F) 可以获取到当前的键盘输入。
  当输入键盘 F 键的时候触发 clickCheck 实现动画开门,再点击就会反过来实现动画关门。
  这个方案可以实现平移开门的实现,但是一旦涉及到旋转门,那设置负值就会让门陷入无限循环的。

Maya模型图片

  因此后期我将旋转相关的代码改为上面图片的实现方案,通过 bing 搜索出来的。

打开电视

  Unity 实现视频播放其实网上也有很多相关的文章。
  我这里是使用 videoPlayer 来实现的。
  通过 videoPlayer 播放视频,然后将视频输出成贴图,然后将相关的贴图贴到对应的材质上,再将材质放到对应的模型上,就可以实现视频播放。
  由于我是直接使用 mp4 视频格式,所以无法播放视频的 音频 ,因此需要提取视频的音频做一个 wav 文件。
  这里是额外添加了一个 audioSource 组件来控制音频。

Maya模型图代码编写片

拾取脚本制作

代码编写

  控制器模型在拾取状态下的旋转缩放。

代码编写

  GameObject.Find("Furniture_Panel").GetComponent<Furniture_Panel>().PickUp 是另一个脚本上的变量,用于判断全局的状态拾取状态。
  判断条件,如果满足可以开启拾取和取消拾取。

代码编写

  拾取之后需要禁用 刚体和碰撞器的相关属性, 还要确保模型在碰撞区域无法 放下物体。
  最后就是在碰撞状态下实现红色高亮显示。
  这个地方没有参考教程,完全是自己写的,因此代码比较粗糙。

Furniture_Panel 编写

  这个面板我花了比较多的心思。
  首先要将面板搭建出来,这里大量参考了 换装教程的设计思路。
  另外因为有 Pyqt 的开发经验,搭建GUI的时候也没有遇到太多的问题。

大纲视图

  首先创建对应的 GUI , Toggle 就是左边的切换按钮, View 就是右边的视图。
  进入程序之后会获取 View 并生成 item ,然后只显示第一个 View 。
  通过 Toggle 切换就可以实现在多个 View 中的切换。

数据字典

GUI 处理

  createImageItem又是怎么实现的呢?
  我做了一个图片 item 的 prefab ,后续就是用代码生成 prefab
  prefab 包括红色的选中边框,图片以及说明文字
  在这里最核心的想法是我希望显示出来的item是自动生成图片,而不需要我对模型一个个去截图的。
  这个制作在 bing 上搜索了很多解决方案,最后使用下面这些函数可以解决我的问题。

代码编写

  给定摄像机和长宽就会渲染出当前摄像机对准的图片。
  那么还需要给个模型定位,让摄像机到对应的位置。

代码编写

  这个方案也是在 bing 上找到的,可以根据模型的boundingbox将摄像机定位到模型附近的区域并望向模型。
  获取到图片就可以批量给生成的 UI 添加图片

代码编写

  这个就是G键面板的主要逻辑。
  生成了物体之后,只要让物体 prefab 执行脚本的 pickUp 函数就可以实现拾取状态。

总结

  这次Unity开发完全是为了应付作业而速成的,很多效果都很渣。
  没有使用第三方的工具包,对Unity不熟悉,害怕坑太多,填不完。
  也没有美工修饰,大部分用Unity的原生方案,模型也很粗糙。
  作业完成就得了(:з」∠)