Unity3D – 第一人称漫游

虚拟漫游可以提升游戏玩家的沉浸感,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 轴旋转方向,在移动角色时,使摄像机跟随角色运动。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注