程 萍
(西华大学机械工程学院四川成都610039)
随着计算机图形学的进步和快速发展的软硬件技术,虚拟现实技术(VR)越来越多的应用到人们的工作、生活、娱乐之中。3D引擎作为一种底层工具支持高层图形软件开发,可以把它看成是对3D API的封装,对一些图形通用算法的封装,对一些底层工具的封装;利用它可以快速开发3D应用而不必关心底层细节,如三维场景中旋转、移动、碰撞、特效等。本文用3dsmax[1]对场景建模,导入U3D引擎中,进行脚本编程实现用户的交互行为控制[2-4]。
本模拟系统主要用于驾校的场地考试模拟训练,三维模拟与传统的现场考试相比,主要有以下优势:(1)便捷。人们可以随时、随地进行驾驶模拟训练;(2)便宜。不用花很多钱去上驾校;(3)省时。在有空时即可打开电脑训练一下,而不用让自己的假期在学车中渡过。当然,本软件有很多细节需要完善,特别是物理仿真这一块。下面,主要介绍UI设计、汽车控制、脚本通信等主要部分。
图1 系统的主要组成
为了提升用户的交互体验,利用UniSkin制作的按钮来响应鼠标事件,如移动、点击等。此外,考虑不同用户机的分辨率不同,制作按钮时采用了显示分辨率的自适应;在模式选择和考试场地选择时,为了给用户眼前一亮的感觉,制作了一组多次放大的移动按钮来吸引用户的眼球。
考虑到用户的屏幕分辨率有多种设置,而采用固定坐标的控件位置会出现错误。针对这种情况,设计一种默认分辩率;然后,获取用户屏幕分辨率,并计算2种分辩率的缩放比例;最后,应用于控件的坐标。具体做法:(1)设计一种默认分辨率为m_fScreenWidth*m_fScreenHeight;(2)获取当前屏幕分辨率 Screen.width*Screen.height;(3)计算缩放因子 m_fScaleWidth=(Screen.width)/m_fScreenWidth;m_fScaleHeight=(Screen.height)/m_fScreenHeight;(4)在控件代码中加入缩放因子。
假设 Button 控件位置(X,Y,Width,Height),其自适应控件位置(X*m_fScaleWidth,Y*m_fS-caleHeight,Width*m_fScaleWidth,Height* m_fS-caleHeight),经测试适用分辨率的自适应。
多次放大移动的效果是:当点击按钮,按钮自动多次放大并向你靠近。这是利用面板来代替按钮;当点击按钮(面板)时改变按钮的三维坐标和旋转坐标,同时改变其缩放比例和背景图片。其中,需要解决如下问题。
(1)如何使点击的二维坐标响应到面板的三维坐标系中?鼠标拣选是解决问题的关键,通过摄像机发出一条射线到点击位置,获取该点的三维坐标,以此判断是否点击到面板。关键代码如下:
(2)获取到按钮被点击的参数后,开始响应按钮的放大和移动。控制按钮(面板)的缩放比例实现移动,改变按钮到摄像机的距离实现放大。
图2 按钮的初始位置和效果
图3 移动中放大按钮的效果
汽车的控制主要是指汽车行驶、转弯、引擎声音的控制。
(1)转向的计算
图4 汽车转向的计算
不考虑汽车侧滑,汽车转弯时各参量关系见图4。
转弯半径:R=(L×ctgα -B)/cosβ (2-1)
R:后轮小圆半径。向左转弯则为左后轮转弯半径,向右转弯则为右后轮转弯半径。
L:前轮毂与后轮毂中心距离。
B:车辆宽度,即左右两轮外缘距离。
α和β:2个后轮的转角。
圆心位置:在车后轮轮毂延长线上。如车辆向左转弯,则圆心在后轮轮毂向左的延长线上;如车辆向右转弯,则圆心在后轮轮毂向右的延长线上。根据转弯半径R即可确定圆心位置。
(2)汽车的控制
汽车的控制主要是通过检测每一帧汽车的速度和转弯角度来计算运动过程。
1)前进和后退
如按住w键,相当于汽车油门。如果一直按住,汽车会以加速度行驶。脚本语句为:
MoveSpeed+=Acceleration*Time.deltaTime
其中,MoveSpeed是汽车前一帧的速度,Acceleration是汽车的加速度,是一个固定值,Time.deltaTime是当前距离上一帧的时间。利用unity3d函数Translate(Vector3)让汽车以Vector3这个三维向量的方向和大小移动。
2)转弯
转弯控制与汽车前进、后退类似,通过按键或者其他输入设备来控制,脚本语句为:
RotAngle+=Va*Time.deltaTime
其中,RotAngle是转弯角度,Va是一个常量,Time.deltaTime是当前距离上一帧的时间。利用RotateAround(Pos,axis,Angle)函数实现;Pos 为旋转中心即转弯圆心,axis是转弯绕axis轴,Angle是旋转角度。
(3)引擎声控制
利用引擎转速来控制一个音效的音高。脚本语句为:
Voice.pitch=rotate/Maxrotate+1
rotate为当前转速,Maxrotate为最高转速。
程序中脚本通信是指2个或以上脚本中的变量或函数等能够互相运用。本文主要是用在获取考试场地(点击选择),以便能够在考试场地中初始化汽车的位置。脚本通信涉及到js与cs信息传递,例js调用cs中变量或函数,因为U3D的脚本调用顺序有先后,Standard Assets、Eidtor、Plugins 3个文件夹下面的脚本先调,如果是cs调用js,那么js必须放在这3个文件夹之一中,否则报错;如果是cs调用cs这种模式,2种cs文件都可以放在这3个文件夹之外,调用变量和函数方法如下。
cs调用cs的变量:被调用的变量必须是 static public类型;然后调用cs脚本名、函数名或变量名;
cs调用 js的变量:testMenu为 js脚本名,carState为js文件中变量,
testMenu c=(testMenu)gameObject.GetComponent<testMenu>();
state=testMenu.carState;
cs调用js的函数:直接用js脚本名、变量名。
为了丰富场地的动态效果,增加趣味性,加入时间和天气因素。UniSky插件能够实现天气的改变以及时间控制。具体操作方式如下:
(1)在Unity3d编辑界面Project版块中鼠标右键选择Import Package引入本地包;
(2)绑定主摄像机;
(3)经过一些设置即可运用。
最简单的例子是:uniSky.SetTime(n)函数用于设置时间,其中n代表设置的时间点。
Unity3d抗锯齿的设置。Unity3d中大部分模型存在锯齿严重的情况。解决这一问题的方法是在
Editor- >Project Setting- >Quality- >Anti Aliasing设置中改成4X或更高,当然,这显著增加了计算时间。只对独立显卡起作用,不适用于集成显卡。效果见图5和图6。
图5 抗锯齿前效果
图6 抗锯齿后效果
[1]时代印象.3ds Max 2012/VRay效果图制作完全自学教程[M].北京:人民邮电出版社,2012.
[2]李瑞森.Unity 3D游戏场景设计实例教程[M].北京:人民邮电出版社.2014.
[3]吴亚峰.Unity游戏案例开发大全[M].北京:人民邮电出版社,2014.
[4]莱莫尔斯.Unity着色器和屏幕特效开发秘笈[M].北京:机械工业出版社,2014.
[5]高雪峰.Unity 3D NGUI实战教程[M].北京:人民邮电出版社,2015.