解密ControlRotation与ActorRotation
在實現角色移動時,我們是通過獲取當前角色向前或者向后移動的向量來計算具體的移動步長,進而增量設置角色位置以達到使角色移動的目的。但是獲取向前或者向后的向量得先知道當前角色在世界坐標系中旋轉的角度,于是我們就在ControlRotation和ActorRotation之間猶豫不定,對二者異同不甚了解,分別表達的意圖也懵懵懂懂,似乎對于初學者總隔著一層面紗,今天我就幫大家揭開它。
有個大前提:只討論第一人稱
首先概念上講,ControlRotation作為控制器的成員變量,在這里是表示人眼睛朝向,ActorRotation表示人身軀的朝向。
如下示意圖,會更明確:
我們可以從常識上理解,人的眼睛在腦袋上,腦袋是可以左右擺頭(Yaw角度變化),可以上下點頭(Pitch角度變化),而人的身軀只能左右轉動(Yaw角度變化),身軀不能僵直地俯仰,這在第一人稱射擊游戲里面不會出現。(反正我沒有見過,你如果見過請告知我)
我們可以通過代碼進一步佐證:
朝向獲取
ControlRotation和ActorRotation的關系
它們兩者的關系,其實主要是理清楚它們分別是怎樣更新的或者其中一個值的更新怎樣影響到另一個值的變化。
1、ControlRotation的更新
我們在開發第一人稱射擊游戲時,通過鼠標的上下左右移動以控制槍的瞄準方向也就是眼睛的朝向,會利用到如下代理綁定:
隨著鼠標移動會使眼睛也保持移動,那么具體ControlRotation怎樣被更新的呢?那么我們通過UE4底層代碼進一步探究,如下圖:
我們先看到我標注的關注1,在此ViewRotation就是ControlRotation,它會在PlayerCameraManager的ProcessViewRotation函數里面被更新,更新的變換值是DeltaRot,這個值是角度的增量變化值。更新好了后,通過SetControlRotation更新ControlRotation值,那么再看ProcessViewRotation函數具體的實現,如下圖:
如上圖的注釋說明,最終值是通過引用做返回,而值的增量更新就是加上了DeltaRot。不過,我們前面就說了ControlRotation實際上就是眼睛的朝向,眼睛朝向按實際情況角度是有限制的,比如向上仰頭肯定不能超過90度,否則頭就斷了(很恐怖的情景)。具體限制的值如下圖:
由此我們終于弄明白了ControlRotation具體更新的過程,實際上就是把增量變化的角度值增加到其上即可,增量變化的角度值與鼠標的位置變化成線性關系。
2、ActorRotation的更新
那ActorRotation是怎樣被更新的,我們回過頭來看《ControlRotation更新算法》圖中的關注2,當更新完了ControlRotation后,會利用它作為參數傳遞到了FaceRotation函數中,那就看一下FaceRotation函數做了什么,如下圖:
我們看到它其實會根據bUseControllerRotaionPictch,bUseControllerRotaionYaw和bUseControllerRotaionRoll開關,分別判斷是否使用ControlRotation的分量角度,最后會通過SetActorRotation函數設置ActorRotation的值,這里也恰好解釋了我們經常在編輯器里面設置的幾個開關,如下圖:
對于射擊游戲,我們設置讓ControlRotation的Yaw值去更新ActorRotation的Yaw值,也就是說眼睛的左右轉向控制角色身軀的左右轉向。
至此,所有謎底我們都已經解開,我們給出一個結論:
在第一人稱射擊游戲中,ControlRotation表示的是角色眼睛的朝向,為了符合現實中的效果,分別對眼睛在Pitch、Yaw、Roll三個轉向上做了限制,ActorRotation表示的是角色身軀的朝向,根據用戶配置,它的Yaw是更新自ControlRotatioin的Yaw值。
不知道大家有沒有一種包公破案的感覺,當然這里要簡單很多,實際在工作中我們碰到的問題也比這要復雜,但是其實解決問題的思路方法一致。
好,大家如果有興趣結合案例去綜合實踐,可以跟著UE4-VR高級課程 虛幻引擎多人在線射擊游戲C++開發實戰(第一季)第六節課《人物前后移動》來做。
歡迎大家加入我們的qq群,跟業內人士共同探討交流。
http://qm.qq.com/cgi-bin/qm/qr?k=nBfAvQJM7Q8hCESjMF39WTlxMzDLVsd0?(二維碼自動識別)
總結
以上是生活随笔為你收集整理的解密ControlRotation与ActorRotation的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2016怎么快速累积招行信用卡积分?看看
- 下一篇: CMake find_package