3.1 自主漫游功能
自主漫游功能是本项目非常重要的功能模块,用户可以通过鼠标进行上、下、左、右、前、后方向控制,还可以结合键盘上空格键——表示向上跳跃,向上箭头——表示前进,向下键——表示后退,向左键——表示向左移动,向右键——表示向右移动,来实现用户在虚拟现实的楼盘中进行室外场景和小区建筑样品房的自主漫游。自主漫游主要是添加了第一人称控制器,使得项目运行时,可以直接用unity3d提供的脚本进行简单的人机交互。
3.1.1 摄像机控制功能
用户除了使用键盘与鼠标的协同合作进行跳跃,前进后退和左右移动外。也可以通过对鼠标与键盘的协同合作对摄像机进行控制来转换场景的位置和角度,其中按下Alt键和鼠标左键可以对场景进行x和z轴方向的移动,当按下Alt键和鼠标右键可以对场景进行y轴方向的移动,按下鼠标中轮时可以拖动鼠标来旋转摄像机的角度,按住中轮滚动可以对场景进行拉近拉远控制,而当设置变得不可回到合适的位置时可通过快捷键H来复位摄像机。摄像机的控制js脚本具体内容如下:
CameraControl.js
public class CameraContorl : MonoBehaviour{
public float minFov=15.0f;
public float maxFov=150.0f;
public float sensitivity=10f;
void Start(){
}
void Update(){
//检测鼠标左键是否按下
bool press_left=Input.GetMouseButton(0);
//检测鼠标右键是否按下
bool press_right=Input.GetMouseButton(1);
//检测鼠标中轮是否按下
bool ScrollWheel=Input.GetMouseButton(2);
//检测alt是否按下
bool alt=Input.GetKey(KeyCode.LeftAlt);
//获得鼠标在水平垂直方向的移动距离
float mx=Input.GetAxis("Mouse X");
float my=Input.GetAxis("Mouse Y");
//鼠标滚轮按下调整角度
if(ScrollWheel){
transform.Rotate(my*2.0f,mx*2.0f,0);
}
//alt+左键按下移动场景
if(press_left & alt){
transform.Translate(-mx*5.0f,0,-my*5.0f,);
}
//alt+右键相机沿Y移动
if(press_right & alt){
transform.Translate(0,-my*5.0f,0);
}
//拉近拉远设置
float fov=Camera.main.fieldOfView;
fov+=Input.GetAxis()*sensitivity;//鼠标滚动距离
fov=Mathf.Clamp(fov,minFov,maxFov);
Camera.main.fieldOfView=fov;
//归位设置
if(Input.GetKeyDown(KeyCode.H)){
Cramera.main.fieldOfView=77.0f;//主摄像机视野参数参考自己原始位置
Cramera.main.transform.position=new Vector3(229.082f,47.74f,42.45f);//主摄像机位置Position
Cramera.main.transform.eulerAngles=new Vector3(11.082f,470.74f,420.45f);//主摄像机角度Rotation
}
}
}
3.1.2 小地图
小地图的实现:
主摄像机设置为满屏,它的深度Depth设置为0,其他摄像机的深度都设置为0。
3.1.2-1 一般摄像机参数
新建摄像机改名为map,将其属性Viewport Tect设置为:X:0,Y:0.7,W:0.3,H:0.3,并将其深度Depth设置为1,则这个摄像机看到的画面将总是出现在深度小于它的摄像机的上面。
3.1.2-2 地图摄像机参数
还要调整摄像机的角度,使其垂直正对整个场景,使整个场景以平面地图的形式显示,这样则小地图就会出现在场景的左上角,且其宽和高都为整个屏幕的十分之三。如此在场景运行时还是无法看到人物控制器所在位置,接下来给人物控制器下的Graphics附一个红色的材质球,将这个组件的大小调整到合适大小。场景运行后就可以看到一个红色圆点随着人物控制器的移动而移动。如此,小地图就做好了。
3.2 GUI界面设计
3.2.1 主界面
主界面主要包括的是查看项目的介绍、项目的操作说明书、自主漫游的场景转换和退出程序的按钮。在主界面可以通过点击项目“操作手册”按钮进入说明文档界面,来了解项目中的注意事项和操作方法。对于场景的选择与转换,界面中点击室外漫游的按钮就可以进入室外场景中。在这以进入自主漫游界面的js代码为例:
function OnGUI(){
if(GUI.Button(Rect(180,300,60,30),"室外漫游")){
Application.LoadLevel("1");//1为室外的场景名称
}
}
3.2.2 室外场景界面
室外场景界面也包含了几个按钮,这些按钮连接着不同的摄像机,当点击某个按钮会转换到对应的摄像机,对不同场景来进行简略浏览,例如“中心花园”、“天涯海角”、“全景鸟瞰”等室外场景中的主要几个小景区。当点击“开始漫游”按钮时,则会进入自主漫游状态,当按了键盘上的Esc键时可以退出漫游系统回到室外场景界面。以下就是点击“全景鸟瞰”所显示的效果。
图3.2.2-1 全景鸟瞰图
3.3 多媒体功能
此功能主要是实现场景中背景音乐的播放与关闭,首先为Terrian添加音源组件,并设置好所播放的音乐和其他相关参数,这里的音乐是本场景一运行就开始播放。然后为主摄像机添加音乐监听组件,这样当场景运行时就可以听到音乐了,为用户营造了舒适的漫游氛围。
3.3.1 为场景设置音乐步骤
导入喜欢的音乐:我导入的是MP3格式的音乐。
3.3.1-1 导入音乐
设置声音监听器:为主摄像机添加监听组件Audio Listener。
图3.3.1-2 添加声音监听组件
设置声音源:为地形Terrian添加声音源组件Audio Source,并设置音乐为所导入音乐wind,使其在场景运行时就开始播放
图3.3.1-3 添加声音源
3.3.2 添加音乐控制按钮
在场景中添加音乐播放和暂停的按钮,当点击“暂停”时音乐暂停,点击“停止”时,音乐停止,点“击播”放时音乐重新播放。脚本Menu.js付给Terrina,脚本详细代码如下:
#pragma strict
function OnGUI(){
if(GUI.Button(Rect(10,160,100,50),"播放")){
Application.Play();
}
if(GUI.Button(Rect(10,220,100,50),"暂停")){
Application.Puase();
}
if(GUI.Button(Rect(10,280,100,50),"停止")){
Application.Stop();
}
}
3.4 样品房展示
样品房为场景1中所示建筑中的某一种户型,房地产项目中除了建筑与室外环境很重要外,户型也是非常重要的一部分。此户型的模型是通过3DMax组合模型而成,首先建好户型的房屋框架,然后制作吊顶和墙壁(包括T脚线的制作),将之前找好的各个房间的模型一个个合并到此个模型中,然后为模型贴图,例如墙壁和地板。将做好的模型导出为FBX格式,导出格式时要注意勾选上一些选框使图片跟着模型走,否则导出的模型放到unity中可能会使模型全部呈现为灰色的模型。选好合适的选项导出模型就可以将模型导入Unity3D中应用了,设置好每个房间的摄像机的角度,然后通过不同摄像机间的转换就可以完成展示不同房间格局和风格的功能,还可以自主漫游整个户型。
在主界面中点击样品房就可进入场景2即样品房展示的场景中,场景主摄像机开始处在户型客厅门口,可以直接开始自主漫游,与室外的自主漫游一样的原理,室内也可以旋转视野和前后左右移动。当想直接从一个准备好的视野查看某一个房间时,此场景中有六个按钮就方便了用户,这六个按钮分别对应了六个个摄像机:camera1——客厅格局、camera2——餐厅格局、camera3——主卧室格局、camera4——浴室格局、camera5——次卧室格局、camera6——书房格局。用户可跟句自己的喜好参观各个房型,或者是做一个简单的自主漫游。
摄像机切换的代码如下:
CameraSelect.js:
var camera1:GameObject;//客厅格局
var camera2:GameObject;//餐厅格局
var camera3:GameObject;//主卧室格局
var camera4:GameObject;//浴室格局
var camera5:GameObject;//次卧室格局
var camera6:GameObject;//书房格局
function OnGUI ()
{
if(GUI.Button(Rect(10,100,100,50),"客厅"))
{
onActiveFalse();
camera1.active=true;
}
else if(GUI.Button(Rect(10,160,100,50),"餐厅"))
{
onActiveFalse();
camera2.active=true;
}else if(GUI.Button(Rect(10,280,100,50),"主卧室"))
{
onActiveFalse();
camera3.active=true;
}else if(GUI.Button(Rect(10,220,100,50),"浴室"))
{
onActiveFalse();
camera4.active=true;
}else if(GUI.Button(Rect(10,280,100,50),"次卧室"))
{
onActiveFalse();
camera5.active=true;
}else if(GUI.Button(Rect(10,340,100,50),"书房"))
{
onActiveFalse();
camera6.active=true;
}
}
//默认都为false
function onActiveFalse()
{
camera1.active=false;
camera2.active=false;
camera3.active=false;
camera4.active=false;
camera5.active=false;
camera6.active=false;
}
部分格局的展示:
图3.4-1 户型-客厅格局
图3.4-2 户型-餐厅格局
图3.4-3 户型-主卧室格局
图3.4-4 户型-浴室格局
3.5 碰撞检测技术
碰撞检测技术是本项目的技术难点。碰撞检测最基本的是模拟现实环境中的物体在遇到障碍物时发生的本能反应。好的碰撞检测要求人物在场景中可以平滑移动,遇到一定高度的台阶可以自动上去,而过高的台阶则把人物挡住,遇到斜率较小的斜坡可以上去,斜率过大则会把人物挡住。同时摄像机也不能穿墙而过,在遇到墙体时停止向前。当然,在各种前进方向被挡住的情况下都要尽可能地让人物沿合理的方向滑动而不是被迫停下。
在unity3d中,能检测碰撞发生的方式有两种,一种是利用碰撞器,另一种则是利用触发器。这两种方式的应用比较广泛。项目中用的是碰撞器方式来实现简单的碰撞检测。系统默认会给每个对象(GameObject)添加一个碰撞组件(ColliderComponent)。第一人称控制器的胶囊体有系统自动赋予的胶囊体碰撞器。Unity3D中有以下接口函数来处理触发信息检测:
1.MonoBehaviour.OnTriggerEnter( Collider other )当进入触发器
2.MonoBehaviour.OnTriggerExit( Collider other )当退出触发器
3.MonoBehaviour.OnTriggerStay( Collider other )当逗留触发器
碰撞检测技术实现的过程中所遇到的困难如下:
1.如何限制角色走到边缘时停止前行;
2.限制角色遇到坡度比较陡的山体不能前行;
3.角色不能任意穿过花草树木建筑等物;
4.角色遇到阶梯时能实现拾级而上。
解决办法:
通过网上的资料收集,逐个逐个问题地一一击破。这里以角色遇到墙体出现提示信息并停止前进为例:
1.给第一人称控制器的胶囊体加钢体组件,并取消刚体组件的重力选项UseGravity;
2.给墙体模型赋予“wall”墙壁角色;
3.只要在钢体和墙壁上都加collider碰撞器;
4.主角碰到墙壁模型后的提示信息主要通过写脚本赋予角色来实现。
脚本代码如下:
function OnCollisionEnter(theCollision : Collision){
if(theCollision.gameObject.name == "Wall"){
Debug.Log("Hit the wall");//遇到墙壁时提醒
}
}
- 上一篇: Unity3d--学生作品22...
- 下一篇: 数字媒体技术专业学...