用Unity實現Minecraft中的鏡頭控制


在學習Unity的過程中,最基本而又最重要的一部分就是鏡頭控制(Camera Control)

鏡頭控制就是通過鼠標、鍵盤等輸入設備的操作,來實現在游戲中的導航。在Unity中的本質是通過接收鼠標的移動和鍵盤的按鍵,來變換相機對象(Camera)的位置(position)和旋轉(rotation),這兩個值位於cameratransform組件(conponent)中。

在這里我們通過實現《我的世界》中創造模式的鏡頭控制方式來學習第一人稱的鏡頭控制。

在我的世界中,鏡頭的朝向(旋轉)是通過鼠標在XY方向的平移來控制的,鏡頭的前后左右移動是通常的WASD鍵,升起(向上移動)為空格鍵,降落(向下移動)Shift鍵。

下面我先給出完整代碼和Demo的建立步驟。運行成功后,我們再進行代碼剖析。

 

建立Demo

1. 新建一個Unity項目。

2. 將下面代碼保存為BasicCameraControl.cs,放到Unity項目的Assets文件夾下。

using UnityEngine;
using System.Collections;

public class BasicCameraControl : MonoBehaviour
{
    float yaw = 0;         // 偏航角,繞Y軸旋轉的角度
    float pitch = 0;       // 俯仰角,繞Z軸旋轉的角度
    const float roll = 0;  // 翻滾角,繞X軸旋轉的角度

    void FixedUpdate ()
    {
        // Move forward or backward
        if (Input.GetKey (KeyCode.W)) 
            transform.position += Vector3.ClampMagnitude (transform.forward, 0.1f);
        else if (Input.GetKey (KeyCode.S)) 
            transform.position -= Vector3.ClampMagnitude (transform.forward, 0.1f);

        // Move left or right
        if (Input.GetKey (KeyCode.A)) 
            transform.position -= Vector3.ClampMagnitude (transform.right, 0.1f);
        else if (Input.GetKey (KeyCode.D)) 
            transform.position += Vector3.ClampMagnitude (transform.right, 0.1f);

        // Move up or down
        if (Input.GetKey (KeyCode.Space)) 
            transform.position += new Vector3 (0, 0.1f, 0);
        else if (Input.GetKey (KeyCode.LeftShift)) 
            transform.position -= new Vector3 (0, 0.1f, 0);

        // Rotate
        pitch -= Input.GetAxis ("Mouse Y") * 5;
        pitch = Mathf.Clamp (pitch, -90, 90);
        yaw += Input.GetAxis ("Mouse X") * 5;
        transform.rotation = Quaternion.Euler (pitch, yaw, roll);
    }
}

3. 為場景中的默認相機對象(Main Camera)添加此腳本組件。具體做法為,選擇Main Camera,在Inspector中點擊底部的Add Component按鈕,點擊Scripts菜單,點擊Basic Camera Control完成。

4. 在場景的中心位置添加一些物體作為移動相機時的參照,比如一個正方體(Cube)

5. 點擊Play按鈕,移動鼠標進行轉向,按下WASD、空格和Shift進行移動。

 

細節解析

1. 鏡頭平移控制

鏡頭的平移實際上是在檢測到鍵盤上WASD、空格、Shift的按下后,修改camera.transform.positonx, y, z分量。

在這里我們需要注意的是,y分量也就是升起和降落,是永遠平行於世界坐標系的y軸的,所以直接修改y分量即可:

transform.position -= new Vector3 (0, 0.1f, 0);

但是對於前進后退和左右平移是不一樣的,因為我們在這四個方向的移動還和我們面朝的方向有關。所以我們通過tansform.forwardtransform.right獲取朝向然后與與transform.position進行加減。

使用Vector3.ClampMagnitude()函數是為了減慢移動速度到合適的程度。

2.鏡頭旋轉控制

關於鏡頭的旋轉我們或許可以用下面的一行代碼實現:

transform.Rotate (- Input.GetAxis ("Mouse Y") * 5, Input.GetAxis ("Mouse X") * 5, 0);

但是這樣無法保證我們的鏡頭始終與地面保持垂直。通過在屏幕上不斷地畫圓圈,我們可以實現倒立。我們不是雜技團,所以這肯定不是我們想要的。

為了避免這種情況發生,我們通過先對旋轉角的分量進行偏移,然后再用Quaternion.Euler()函數轉換為四元數即可。

3.為什么用FixedUpdate()

Update()FixedUpdate()的區別是Update()是隨渲染(Render)過程發生的。而FixedUpdate()是按照固定的周期發生的,也就是說即使由於畫面上人物眾多,刷新率降低,也能保證函數執行的次數恆定。

了解到這些,我們就可以設想。假如我們在Minecraft中進行一場賽跑,一台高配台式電腦以60FPS運行,而一台筆記本以平均30FPS運行。如果我們用Update()來驅動人物運動的話,那么筆記本上的人物肯定移動沒有台式機快。這樣肯定不符合公平的原則,所以我們在這里必須使用FixedUpdate()

End


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM