虚拟漫游可以提升游戏玩家的沉浸感,Unity 3D 中提供了第一人称以及第三人称虚拟漫游的组件。
GameObject – 3D Object – Plane 创建平面
GameObject – Create Empty 创建空物体
Inspector – Tags – Add Tag 添加标签
一个标签是用来索引一个或一组游戏对象的词。标签是为了编程的目的而对游戏对象的标注,游戏开发人员可以使用标签来书写脚本代码,通过搜索找到包含想要的标签的对象。
Component – Physics – Character Controller 角色控制器
主要用于第三人称或第一人称游戏主角控制,具体参数如下表所示。
参 数 | 含 义 | 功 能 |
---|---|---|
Slope Limit | 坡度限制 | 限制碰撞器只能爬小于等于该值的斜坡。 |
Step Offset | 台阶高度 | 角色可以迈上的最高台阶高度。 |
Skin Width | 皮肤厚度 | 皮肤厚度决定了两个碰撞器可以互相渗人的深度。 |
Min Move Distance | 最小移动距离 | 如果角色移动的距离小于该值,角色就不会移动。 |
Center | 中心 | 该值决定胶囊碰撞器在世界空间中的位置。 |
Radius | 半径 | 胶囊碰撞器的横截面半径。 |
Height | 高度 | 胶囊碰撞器的高度。 |
放置于世界中注意调整位置和大小,使其置于平面上。
Rigidbody 刚体设置
勾选 Use Gravity 复选框使控制器受物理系统影响。
勾选 Is Kinematic 复选框使控制器需要在非常明确的用户控制下进行移动。
Dynamic:这种刚体类型具有可用的全套属性(例如有限质量和阻力),并受重力和作用力的影响。Dynamic 刚体类型将与每个其它刚体类型碰撞,是最具互动性的刚体类型。这是需要移动的对象的最常见刚体类型,因此是2D刚体的默认刚体类型。此外,由于具有动态性并与周围所有对象互动,因此也是性能成本最高的刚体类型。选择此刚体类型时,所以2D刚体属性均可用。
Kinematic:这种类型的2D刚体仅在非常明确的用户控制下进行移动。虽然Dynamic2D 刚体受重力和作用力的影响,但 Kinematic2D 刚体并不会受此影响。因此,Kinematic2D 刚体的速度很快,与 Dynamic 比,对系统资源的需求更低。
Kinematic2D 刚体仍然通过速度移动,但是此速度不受作用力和重力的影响。Kinematic2D 刚体不会与其它 Kinematic2D 刚体和 Static2D 刚体碰撞,只会与 Dynamic2D 刚体碰撞。与 Static2D 刚体相似,Kinematic2D 刚体在碰撞期间的行为类似于不可移动的对象(就像具有无限质量)。选择此刚体类型时,与质量相关的属性将不可用。
(简单来说,Kinematic 只能通过更改刚体的速度属性来改变位置,不会受到其它物理效果的影响。)
Static2D 刚体设计为在模拟条件下完全不动(Play 模式);如果任何对象与Static2D 刚体碰撞,此刚体类型的行为类似于不可移动的对象(就像具有无限质量)。此刚体类型也是使用资源最少的刚体类型。Static 刚体只能与Dynamic2D 刚体碰撞。不可支持两个 Static2D 刚体进行碰撞,因为这种刚体不是为了移动而设计的。
控制角色移动的代码如下:
using UnityEngine;
using System.Collections;
public class Player:MonoBehaviour{
public Transform m_transform;
//角色控制器组件
CharacterController m_ch;
//角色移动速度
float m_movSpeed = 3.0f;
//重力
float m_gravity = 2.0f;
void Start(){
m_transform = this.transform;
//获取角色控制器组件
m_ch = this.GetComponent<CharacterController>();
}
void Update(){
Control();
}
void Control(){
//定义3个值控制移动
float xm = 0, ym = 0, zm = 0;
//重力运动
ym -= m_gravity * Time.deltaTime;
//前后左右移动
if(Input.GetKey(KeyCode.W)){
zm += m_movSpeed * Time.deltaTime;
}else if(Input.GetKey(KeyCode.S)){
zm -= m_movSpeed * Time.deltaTime;
}
if(Input.GetKey(KeyCode.A)){
xm -= m_movSpeed * Time.deltaTime;
}else if(Input.GetKey(KeyCode.D)){
xm += m_movSpeed * Time.deltaTime;
}
//使用角色控制器提供的Move函数进行移动
m_ch.Move(m_transform.TransformDirection(new Vector3(xm, ym, zm)));
}
}
在 Start 函数中,首先获取 CharacterController 组件,然后在 Control 函数中通过键盘操作获得 X 和 Y 方向上的移动距离,最后使用 CharacterController 组件提供的 Move 函数移动角色。
使用 CharacterController 提供的功能进行移动时,会自动计算移动体与场景之间的碰撞。
在 Hierarchy 视图中选中 Player 游戏对象,在其 Inspector 属性面板中选择 Component – Script,选择 Player 脚本将其链接到 Player 游戏对象上。
将摄像机与主角的游戏对象关联起来:
//摄像机Transform
Transform m_camTransform;
//摄像机旋转角度
Vector3 m_camRot;
//摄像机高度
float m_camHeight = 1.4f;
//修改Start函数, 初始化摄像机的位置和旋转角度
void Start(){
m_transform = this.transform;
//获取角色控制器组件
m_ch = this.GetComponent<CharacterController>();
//获取摄像机
m_camTransform = Camera.main.transform;
Vector3 pos = m_transform.position;
pos.y += m_camHeight;
m_camTransform.position = pos;
//设置摄像机的旋转方向与主角一致
m_camTransform.rotation = m_transform.rotation;
m_camRot = m_camTransform.eulerAngles;
//锁定鼠标
Screen.lockCursor = true;
}
void Update(){
Control();
}
void Control(){
//获取鼠标移动距离
float rh = Input.GetAxis("Mouse X");
float rv = Input.GetAxis("Mouse Y");
//旋转摄像机
m_camRot.x -= rv;
m_camRot.y += rh;
m_camTransform.eulerAngles = m_camRot;
//使角色的面向方向与摄像机一致
Vector3 camrot = m_camTransform.eulerAngles;
camrot.x = 0;camrot.z = 0;
m_transform.eulerAngles = camrot;
//操作角色移动代码
//使摄像机位置与角色一致
Vector3 pos = m_transform.position;
pos.y += m_camHeight;
m_camTransform.position = pos;
}
上述代码通过控制鼠标旋转摄像机方向,使角色跟随摄像机的 Y 轴旋转方向,在移动角色时,使摄像机跟随角色运动。