unity中建筑模型以unity第一人称摄像机漫游后怎么鸟瞰

--------------------------------------------------------------------------
昨天已经完成了场景的基本搭建,今天先简单的实现城市漫游功能,具体细节之后再进行添加
1.导入人物
在Assets文件夹下,新建一个文件夹,用于存放预制体,命名为Prefabs
打开昨天导入进去的SimplePeople资源包,打开其中的示例场景,然后我们可以进去挑选人物啦~
博主在这里选了一个画风清奇,很像程序员的一个人物&SimplePeople_BusinessMan_White&,选中,并将其拖放到Prefabs文件夹下
这样人物就准备就绪了。
2.设置场景
回到游戏场景(我命名的是&GameScene&),全选所有的地形(摄像机暂时除外),道路啊建筑啊,统一加上组件&MeshCollider&,方便与人物碰撞
3.将人物放置于场景
拖拽Prefabs文件夹里的人物到Scene视图,并为其添加CharacterController,设置属性如下
找到人物的位置,点击运行,可能会发现人物往下掉,这是因为刚才添加MeshCollider的时候,部分折叠的没有被添加上去,我们手动添加。
(报了很多错误,不过以前没有出现,并且错误暂时不影响游戏运行,最近会找一下原因所在,大家也可以在评论区指点一下,人多力量大^_^)
这时候人物就不会掉下去了,但是我们会发现,没有办法控制人物的移动,这就需要添加脚本进行控制了。
4.控制人物移动
在Scripts文件夹下,新建一个C#脚本,命名为&CharacterControl.cs&,代码如下
1 using UnityE
2 using System.C
4 public class CharacterControl : MonoBehaviour
//控制速度
public float moveSpeed = 10.0f;
public float rotateSpeed = 1.0f;
public float jumpSpeed = 4.0f;
//跳跃速度
public float gravity = 1;
//重力拉扯
private bool isMainPlayer = false;
private Animator personA
private CharacterC
public bool isJ
private bool isM
private CollisionF
private Vector3 moveD
// Use this for initialization
void Start()
if (this.gameObject.tag == "Player")
isMainPlayer = true;
cc = this.GetComponent&CharacterController&();
personAnimator = gameObject.GetComponent&Animator&();
// Update is called once per frame
void Update()
//如果当前脚本的对象是游戏者
if (isMainPlayer)
//控制移动或旋转
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
h *= Time.deltaTime * moveS
v *= Time.deltaTime * moveS
transform.Translate(h, 0, v);
transform.Rotate(0, h * rotateSpeed, 0);
//FIX THIS BUG:无法后退,因为还没有设置后退的动画
if (Mathf.Abs(Input.GetAxis("Vertical")) & 0.1f)
personAnimator.SetFloat("Speed_f", moveSpeed);
personAnimator.SetFloat("Speed_f", 0);
//按下空格跳跃
//两种跳跃情况:原地跳和一边跑一边跳(脑补出表情包...)
if (Input.GetKeyDown(KeyCode.Space) && !isJump)
personAnimator.SetBool("Jump_b", true);
isJump = true;
moveDirection = transform.TransformDirection(moveDirection);
moveDirection.y = jumpS
else if (Input.GetKeyUp(KeyCode.Space))
personAnimator.SetBool("Jump_b", false);
//if (isJump)
//模拟重力
moveDirection.y -= gravity * Time.deltaT
flags = cc.Move(moveDirection * Time.deltaTime);
//when hit the ground
if (flags == CollisionFlags.Below)
isJump = false;
接下来把脚本赋给人物,需要注意的就是,这段代码是根据Tag去判断是否为游戏者的(因为后期可能会添加一些自由移动的NPC),所以需要把人物的Tag设置为Player。
进入游戏,发现人物可以移动了,不过摄像机还不会跟随人物移动。
5.设置摄像机跟随
unity5.x的摄像机脚本与4有不同之处,所以我们先选一种简单的方法。
首先将Hierarchy中_Scene下的摄像机拖动到人物下。
设置摄像机属性如图
现在就可以漫游了。接下来就是控制动画的播放以及其他的细节处理了。
阅读(...) 评论()这是上学期的一次课程作业,难度不高但是也一并记录下来,偷懒地拿课程报告改改发上来。
课程要求:使用sketchUp建模,在Unity3D中实现场景漫游和场景互动。
知识点:建模、官方第一人称控制器、网格碰撞器、刚体、触发器、射线(触发)碰撞器。
基于SketchUp和Unity 3D的虚拟场景漫游和场景互动(增强现实)
实验要求是实现虚拟场景漫游和增强显示效果。
我们组的项目模型采用SketchUp的小作业房屋设计模型修改而来,最终通过两张房屋设计图分别设计了两套住房模型:图略。
增强现实效果实现
将模型导入Unity3d中后,进一步细化贴图和场景,导入官方package以加入第一人称角色控制器,对模型加入碰撞器,实现了场景漫游并结合第一人称角色控制器的camera加入射线碰撞器,实现注视特定目标可以显示出目标信息(左上角第一个显示栏,如“这是老韩家吃饭的地方”),对于特殊目标设定对应的Text 3D效果,实现类似增强现实的场景效果(如餐桌上方浮现的“Let’s Eat!”),加入触发器可以显示出当前所在位置(左上角第一个显示栏,如“welcome to 老韩家的客厅”)。
我们设立了多处地点触发显示和多处特定目标信息显示,对于餐桌、房屋、电视机和床加入了增强现实的Text 3D效果,具体实现将在设计过程中展示。
具体流程(重点)
创建SketchUp模型
生成fbx文件
将SketchUp中的模型导入Unity 3D中需要使用SketchUp 2016 pro并生成fbx文件及其贴图文件和文件夹,在实际操作中我们还注意到由于房顶等模型材质具有双面不同贴图的情况,结合网上博客了解到生成fbx文件时需要如下设置:
其中选项部分需要如下设置:
创建Unity场景
在Unity 3D中创建项目,生成Assert文件夹,创建场景在Assert文件夹下:
Terrian、Light和Skybox制作
在场景中加入第一个3D模型——Terrian,其中可以加入树木、草、地形和地面贴图,我们采用绿色草地的贴图效果
而Light我们使用,并在房屋中设置了,优点是可以使得漫游时照亮房屋,方便观察操作,缺点是不符合实际日照情况。
Skybox我们先后使用了Standard Assert自带的Skybox和Assert Store中的Skybox,效果均不理想,最后放弃加入Skybox,使用默认场景。
fbx移入场景中并贴图
将之前导出的fbx文件及其贴图文件夹移动到Assert文件夹中,由于Unity自身原因,并不能自动将贴图文件和模型完美结合,需要自行贴图,即在Albedo中拖入贴图文件夹下的对应图片,由于图片命名和模型命名不完全相同,有一些模型结果并不理想。(此过程及其繁琐)
加入第一人称角色控制器
如果要自行实现角色控制并漫游,难度过高,我们选择导入官方package即Standard Assert:
导入后效果如下:
而角色控制器分为:
我们选择了第一人称角色控制器,一方面是因为第三人称角色控制器为了实现摄像头跟踪要加入smooth follow而且并不理想,另一方面我们实现的增强现实效果,即注视物体显示信息和Text 3D效果通过第一人称角色控制器来实现射线碰撞器更为方面,需要注意的是,为了通过某些狭窄的通道,可能需要更改角色的XYZ大小,也应该同步更改offset步长,否则会报错。
模型加入碰撞器属性
碰撞器是极为重要的一环,因为为了实现增强现实效果(注视现实物体信息和Text 3D模型),所有物体都要选择是否作为碰撞体,在Unity中设置如下:
因为大多数模型,包括房屋家具等都是复杂的多面体模型,所以需要使用Mesh Colider(网格碰撞器),在网格碰撞器的具体实现中我们注意到了以下几个关键点:
如果一个父物体加入了Mesh Colider组件,那它的所有子物体都必须加入Mesh Colider组件,拥有子物体的物体模型有很多:
Mesh Colider组件中有Convex(相互碰撞)的选项,大多数物体我们需要勾选,但是在具体实现中,我们将房屋的Convex选择不勾选,并将门的门框(仅仅是门框,不是整个门)不作为Mesh Colider碰撞体,可以使得角色方便进入,但是仍然会和门碰撞,不会穿过门板。
调试时候出现了部分模型Convex不通过的问题,原因是对应的Mesh超过了255个面,我们将这个模型(一盆花)不勾选Convex,即可。
大多数碰撞体结果如下:
加入trigger触发器物体并隐藏
我们另一个技术点是实现显示身处位置,即“welcome to 老韩家的客厅”,具体实现需要先设置触发器,我们在多个地点设置了cube模型的触发器,包括客厅、厕所、厨房、卧室、房屋外:
触发器的效果是隐藏物体:
并设置成可穿过的物体:
一一对应模型信息并加入Text 3D的文字模型
为了实现增强现实效果,即注视物体显示物体信息,我们将很多模型信息记录下来,Tag是模型的名称记录,方便脚本中对应实现:
为了实现Text 3D的模型效果,我们加入了Text 3D模型:
命名为对应的text+对应的模型tag,并设置为隐藏,只有观测到对应模型时才会显示:
编写RayTest2.cs脚本,实现射线碰撞器
做好了碰撞器和Text 3D模型,我们编写了对应的脚本:
在Start()函数中,进行字典的初始化,即将碰撞物体及其信息一一对应:
在Update()函数中,在每一帧进行以camera为射线起点,以camera方向为射线方向,长度为100的射线碰撞,并返回碰撞到的物体信息:
在OnGUI()函数中,输出射线碰撞到的物体对应的字典信息:
同时检测是否有对应的Text 3D模型,有则将其显示:&
也会记录前一次的碰撞物体,如果不同,则说明视线转移了,之前的Text 3D继续隐藏:
编写TriggerTest2.cs脚本,实现触发器
比较简单,见附代码。
完成之后可以在Unity
3D中运行查看,可以生成exe文件运行,在Console中可以显示Debug信息,通过调试的一点人生の经验:
在室内向房顶看去,房顶显示为透明,是因为fbx导出时没有选择双面材质。
Terrain加入草的元素时没有效果,是因为草的Height需要 & 0。
第一人称角色控制器不能移动,是因为模型大小更改以后,要同时更改offset步长。
显示模型Convex错误,是因为过于复杂的物体如一盆花的Mesh网格超过了255个,取消掉其Convex选项即可。
物体添加了Mesh Conlider之后仍然会直接穿过,原因是其子物体也要全部加上Mesh Conlider组件。
注意整个场景中只能包含一个监视器,一般将后加入的监视器去掉,即去掉第一人称角色控制器中的MainCamera。
Unity学习笔记
碰撞器和触发器的区别
碰撞器与触发器[Unity]
RayTest2.cs
using UnityE
using System.C
using System.Collections.G
using System.T
public class RayTest2 : MonoBehaviour {
public string cur = "";
public string fro = "";
public Dictionary&string, string& dic = new Dictionary&string, string&();
// Use this for initialization
void Start () {
dic.Add("Mesh390","老张家的房子");
dic.Add("Mesh230", "老张家的书桌");
dic.Add("Mesh298", "老张家的书桌");
dic.Add("Mesh220", "老张家的电脑桌!");
dic.Add("Mesh249", "老张家的沙发");
dic.Add("Mesh253", "老张家的沙发");
dic.Add("Mesh250", "老张家的沙发");
dic.Add("Mesh252", "老张家的沙发");
dic.Add("Mesh389", "老张家的电视机");
dic.Add("Mesh239", "老张家的隔断");
dic.Add("Mesh231", "老张家的一盆花");
dic.Add("Mesh232", "老张家的一盆花");
dic.Add("Mesh290", "老张家的一盆花");
dic.Add("Mesh291", "老张家的一盆花");
dic.Add("Mesh13", "老张家的大床");
dic.Add("Mesh21", "老张家的大床");
dic.Add("Mesh29", "老张家的大床");
dic.Add("Mesh246", "老张家吃饭的地方");
dic.Add("Mesh198", "老张家的衣柜");
dic.Add("Mesh205", "老张家的衣柜");
dic.Add("Mesh305", "老张家的衣柜");
dic.Add("Mesh292", "老张家的马桶!");
dic.Add("Mesh293", "老张家的马桶!");
dic.Add("Mesh265", "老张家的厨房一套");
dic.Add("Mesh266", "老张家的厨房一套");
dic.Add("Mesh267", "老张家的厨房一套");
dic.Add("Mesh1812","老韩家的房子");
dic.Add("Mesh31", "老韩家吃饭的地方");
dic.Add("Mesh1327", "老韩家的大桌子");
dic.Add("Mesh121", "老韩家的衣柜");
dic.Add("Mesh126", "老韩家的衣柜");
dic.Add("Mesh131", "老韩家的衣柜");
dic.Add("Mesh136", "老韩家的衣柜");
dic.Add("Mesh141", "老韩家的衣柜");
dic.Add("Mesh103", "老韩家的沙发");
dic.Add("Mesh116", "老韩家的茶几");
dic.Add("Mesh1315", "老韩家的洗衣机");
dic.Add("Mesh1322", "老韩家的厨房一套");
dic.Add("Mesh40", "老韩家的环绕音响");
dic.Add("Mesh64", "老韩家的环绕音响");
// Update is called once per frame
void Update ()
Ray ray=new Ray(Camera.main.transform.position,Camera.main.transform.forward*<span style="color: #0);
Debug.Log(ray);
if(Physics.Raycast(ray,out hitcur,<span style="color: #0))
cur = hitcur.collider.gameObject.name.ToString();
Debug.Log(cur);
void OnGUI()
GUI.Box(new Rect(<span style="color: #, <span style="color: #, <span style="color: #0, <span style="color: #), "这是" + dic[cur]);
catch (Exception e)
GUI.Box(new Rect(<span style="color: #, <span style="color: #, <span style="color: #0, <span style="color: #), "");
if (fro == cur)
GameObject obj2 = GameObject.Find("text" + fro);
obj2.GetComponent&Renderer&().enabled = false;
catch (Exception e) { };
GameObject obj = GameObject.Find("text" + cur);
obj.GetComponent&Renderer&().enabled = true;
}catch (Exception e) { };
TriggerTest2.cs
using UnityE
using System.C
using System.Collections.G
using System.C
using System.Collections.G
using System.T
public class TriggerTest2 : MonoBehaviour {
public string cur_room = "outside1";
public Dictionary&string, string& dic = new Dictionary&string, string&();
// Use this for initialization
void Start () {
dic.Add("outside1","北京地下室群居房区");
dic.Add("house1room11","老张的客厅");
dic.Add("house1room12","老张的客厅");
dic.Add("house1room13","老张的客厅");
dic.Add("house1room21","老张的卧室A");
dic.Add("house1room31","老张的厕所");
dic.Add("house1room41","老张的厨房");
dic.Add("house1room51","老张的卧室B");
dic.Add("house1room61","老张的卧室C");
dic.Add("outside2","北京地下室群居房区");
dic.Add("house2room11","老韩的客厅");
dic.Add("house2room12","老韩的客厅");
dic.Add("house2room21","老韩的卧室A");
dic.Add("house2room31","老韩的卧室B");
dic.Add("house2room41","老韩的卧室C");
dic.Add("house2room51","老韩的厨房");
dic.Add("house2room61","老韩的厕所");
// Update is called once per frame
void Update () {
//Debug.Log(cur_room);
void OnGUI()
GUI.Box(new Rect(<span style="color: #, <span style="color: #, <span style="color: #0, <span style="color: #), "welcome to " + dic[cur_room]);
catch (Exception e) { };
void OnTriggerEnter(Collider collider)
//进入触发器执行的代码
cur_room = collider.gameObject.name.ToString();
阅读(...) 评论()

我要回帖

更多关于 unity3d第一人称视角 的文章

 

随机推荐