Unity基礎包 FirstPersonController下的MouseLook 腳本研究

原文鏈接:點擊打開鏈接


版本:unity 5.3.4  語言:C#
 
又不知道要做什麼了,這週週末把Animator的基礎部分刷了,跟模型結合的比較緊密,代碼其實沒什麼,就是非常羨慕熟練操作3dsmax的美工們。
 
反正看看基礎包吧,上一次的FirstPersonController寫的不是很詳細,這次我儘量寫的詳細一點,只是四元數這個玩意我還是不太理解,還是Euler角容易一些。
 
看看這裏面的代碼,雖然半蒙半猜還算看得懂,但什麼時候自己也能寫出如此優秀的代碼呢?
 
今天分析了一下MouseLook,主要是處理人物和鏡頭的旋轉:
[csharp] view plain copy 
public class MouseLook  
{  
    public float XSensitivity = 2f; //x軸和y軸的靈敏度  
    public float YSensitivity = 2f;  
  
    public bool clampVerticalRotation = true;   //是否鎖定x軸的旋轉角度,旋轉的解釋見下  
    public float MinimumX = -90F;   //鎖定的最小、最大角度  
    public float MaximumX = 90F;  
  
    public bool smooth; //是否使用插值運算  
    public float smoothTime = 5f;   //插值的時間  
  
    public bool lockCursor = true;  //是否要檢測鎖定指針  
  
  
    private Quaternion m_CharacterTargetRot;    //角色和相機的目標旋轉角度  
    private Quaternion m_CameraTargetRot;  
  
    private bool m_cursorIsLocked = true;   //當前鼠標指針是否鎖定,只有lockCursor爲true的時候,該值纔會有效  
  
    // 初始化,傳入角色和相機的旋轉角度  
    public void Init(Transform character, Transform camera)  
    {  
        m_CharacterTargetRot = character.localRotation; //角色的旋轉角度  
        m_CameraTargetRot = camera.localRotation;   //相機的旋轉角度  
    }  
  
    // FirstPersonController每幀會調用  
    // 根據鼠標移動的位置調整鏡頭的旋轉  
    public void LookRotation(Transform character, Transform camera)  
    {  
        // 獲取鼠標的位置,乘以靈敏度,獲取x軸y軸的旋轉  
        // 注意這邊的位置是相對位置,也就是這一幀和上一幀的相對移動位置  
        float yRot = CrossPlatformInputManager.GetAxis("Mouse X") * XSensitivity;     
        float xRot = CrossPlatformInputManager.GetAxis("Mouse Y") * YSensitivity;  
  
        // 旋轉,y軸旋轉角色,x軸旋轉鏡頭,也就是說橫向的旋轉是旋轉的角色,而縱向的旋轉是旋轉鏡頭。  
        // 這裏有個好處,就是鏡頭Camera節點是在FPC節點下面的,所以旋轉了角色的同時也會旋轉鏡頭,同時兼顧了旋轉角色的正方向。  
        // 而縱向的旋轉,其實對實際角色而言沒有任何影響,所以只要旋轉鏡頭即可,這種分層次的旋轉十分有用。  
        m_CharacterTargetRot *= Quaternion.Euler (0f, yRot, 0f);    //然後說一下這邊API的使用,大家剛看到一個乘法,可能跟我一樣有些懵逼,不過這邊乘以一個歐拉角,相當於旋轉增加該值,而增加的就是Transform面板上Rotation的值了,所以要使用面板Rotation值的話一定要記住使用歐拉角,而不是普通的創建,普通的創建那是四元數  
        m_CameraTargetRot *= Quaternion.Euler(-xRot, 0f, 0f);  
  
        // 鎖定x軸的旋轉角度  
        if(clampVerticalRotation)  
            m_CameraTargetRot = ClampRotationAroundXAxis (m_CameraTargetRot);  
  
        if(smooth)  //使用插值運算平滑旋轉速度,不過我打開了感覺頭暈,不知道爲什麼。第三人稱用這類插值運算應該很舒服。  
        {  
            // Slerp使用球形進行插值  
            character.localRotation = Quaternion.Slerp (character.localRotation, m_CharacterTargetRot,  
                smoothTime * Time.deltaTime);  
            camera.localRotation = Quaternion.Slerp (camera.localRotation, m_CameraTargetRot,  
                smoothTime * Time.deltaTime);  
        }  
        else     //直接賦值  
        {  
            character.localRotation = m_CharacterTargetRot;  
            camera.localRotation = m_CameraTargetRot;  
        }  
  
        UpdateCursorLock();  
    }  
  
    public void SetCursorLock(bool value)  
    {  
        lockCursor = value;  
        if(!lockCursor)  
        {  
            // 如果用戶主動設置lockCursor,即InternalLockUpdate不會影響是否鎖定指針,則我們強制解鎖指針  
            // 也就是說,lockCursor爲true時快捷鍵影響鎖定指針,lockCursor爲false的時候快捷鍵不影響,並強制不鎖指針  
            Cursor.lockState = CursorLockMode.None;  
            Cursor.visible = true;  
        }  
    }  
  
    // 鼠標指針鎖定有關,FirstPersonController的Update中會調用一次外,MouseLook的LookRotation中也會調用一次  
    public void UpdateCursorLock()  
    {  
        //如果設置lockCursor,則檢查確認是否要鎖定指針  
        if (lockCursor)  
            InternalLockUpdate();  
    }  
  
    private void InternalLockUpdate()  
    {  
        if(Input.GetKeyUp(KeyCode.Escape))  //按下esc,退出指針鎖定  
        {  
            m_cursorIsLocked = false;  
        }  
        else if(Input.GetMouseButtonUp(0))  //按下鼠標左鍵,指針鎖定  
        {  
            m_cursorIsLocked = true;  
        }  
  
        if (m_cursorIsLocked)  
        {  
            Cursor.lockState = CursorLockMode.Locked;   //指針狀態變爲鎖定  
            Cursor.visible = false; //並隱藏  
        }  
        else if (!m_cursorIsLocked)  
        {  
            Cursor.lockState = CursorLockMode.None; //釋放鼠標指針  
            Cursor.visible = true;  
        }  
    }  
  
    // 鎖定鏡頭的旋轉角度,鏡頭只跟X軸旋轉有關  
    Quaternion ClampRotationAroundXAxis(Quaternion q)  
    {  
        // 嗯,網上看了半天的四元數,沒太理解就不強行解釋了,等過段時間研究一下矩陣和四元數  
        q.x /= q.w;  
        q.y /= q.w;  
        q.z /= q.w;  
        q.w = 1.0f;  
  
        float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);  
  
        angleX = Mathf.Clamp (angleX, MinimumX, MaximumX);  
  
        q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleX);  
  
        return q;  
    }  
  
}  


OK,我會繼續分析基礎包中剩下的代碼的,同時也會加把勁把Unity書中基礎部分給刷掉。

發佈了39 篇原創文章 · 獲贊 85 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章