unity3D:遊戲分解之角色移動和相機跟隨
阿新 • • 發佈:2017-05-06
ini img form static 錄像 void 方法 lda okr
遊戲中,我們經常會有這樣的操作,點擊場景中某個位置,角色自動移動到那個位置,同時角色一直是朝向那個位置移動的,而且相機也會一直跟著角色移動。有些遊戲,鼠標滑動屏幕,相機就會圍繞角色旋轉。
看似很簡單的操作,那麽到底是怎麽實現的呢?
我們把上述操作分解為以下幾個步驟
角色的移動
1. 移動到下一個路點,線性插值、曲線插值
2. 角色朝向,一直面朝下一個路點
相機跟隨角色
1. 相機俯視角度,決定相機的高度
2. 相機跟隨距離,前向距離或者直線距離(就是三角形的水平邊長或者斜邊長)
3. 相機一直看角色的後背(Y軸旋轉角度和角色一致)
4. 相機圍繞角色旋轉
技術點:
1. 向量
2. 旋轉
先來看效果,請原諒我未註冊屏幕錄像orz
角色移動
包括位移和方向,就是移動角色的同時角色一直要朝向移動的方向。
左邊的圖,角色從A移動到B,朝向卻一直是向前方的,明顯不符合跑動的顯示邏輯。正確的表現是右圖所展示那樣,角色面朝移動方向。
那麽我們要怎麽做才能實現這個效果呢?位移很簡單,A到B的坐標插值。
其次是旋轉角色,Unity提供了一個方法Quaternion.LookRotation。關於這個方法,官方的解釋如下:
Quaternion.LookRotation 註視旋轉
static function LookRotation (forward : Vector3, upwards : Vector3 = Vector3.up) : Quaternion Description描述 Creates a rotation that looks along forward with the the head upwards along upwards 創建一個旋轉,沿著forward(z軸)並且頭部沿著upwards(y軸)的約束註視。也就是建立一個旋轉,使z軸朝向view y軸朝向up。 Logs an errorif the forward direction is zero. 如果forward方向是0,記錄一個錯誤。
光看描述,是不是比較難理解。網上對這個方法的解釋也挺多的,但是各說紛紜,沒個簡單明了的說法,更容易誤導人。
我們知道向量,包含大小和方向。大小很容易得到,那麽方向怎麽獲得呢?常規來說,可以通過把向量分解為x、y、z三個分量,然後通過三角函數依次求得個分量的夾角。 Unity提供了更簡單的方法,就是Quaternion.LookRotation,這個方法就是獲得傳入向量的方向,即旋轉值,是個四元數。 代碼實際上很簡單,就幾行。主要是要理解為什麽1 //想想為什麽Quaternion.Euler(0, rotation.y, 0)這裏x和z方向都是填的0? 因為角色的朝向是根據偏轉角Yaw,也就是Y軸決定的,x和z軸是沒有發生偏轉的,倘若改變x軸z軸旋轉值,就會發現角色會有俯仰、翻滾的效果。 相機跟隨角色 好了,角色的朝向解決了。那麽,如果我要讓相機一直跟著角色走,同時相機一直看到角色的後背,也就是角色旋轉時,相機要跟著轉動,同時保持固定距離,該如何實現? 我們先計算相機的位置,然後在旋轉相機朝向角色的後背。 1. 計算相機的旋轉值,這裏需要指定相機的俯仰角Pitch的值,假定是30度,可以根據具體情況調節計算當前位置到下一個坐標點的向量 2 var vector = (posB - posA).normalized; 3 //取得向量的方向 4 var rotation = Quaternion.LookRotation(vector).eulerAngles; 5 //將物體旋轉到指向下一個坐標點的方向 6 transform.rotation = Quaternion.Euler(0, rotation.y, 0); 7 //設置物體的坐標 8 transform.position = posB;
//相機的俯仰角和偏航角,Y方向偏航和目標對象一致 Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y, 0);2. 計算指定長度Distance的向量,這個向量是與世界坐標z方向平行
var vector = Vector3.forward * Distance;
3. 用上面的相機旋轉值左乘第二步得到的向量,改變這個向量的方向( 四元數左乘向量,改變向量的方向)
vector = ro * vector;4. 用目標位置減去vector,得到指向目標位置的坐標點,也就是相機的最終位置。(為什麽這樣就得到位置了,回去看看向量的知識吧)
var pos = transform.position - vector;5. 最後,將旋轉值和坐標賦值給相機,相機就完成了跟隨效果, 是不是很簡單
CameraGo.transform.position = pos;
CameraGo.transform.rotation = ro;
1 //相機的俯仰角和偏航角,Y方向偏航和目標對象一致 2 Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y, 0); 3 //給向量賦予旋轉 4 var distanceVector = ro * Vector3.forward * Distance; 5 var pos = transform.position - distanceVector; 6 CameraGo.transform.position = pos; 7 CameraGo.transform.rotation = ro;至於相機圍繞角色旋轉,我們只需要改變一下Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y, 0) 中transform.rotation.eulerAngles.y這個值 本來這個值是指定相機朝向角色的方向,我們改變這個值,就可以實現相機圍繞角色的效果。我們可以這樣做
//delta就是圍繞角色旋轉的旋轉角度0~360.
Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y + delta, 0)
最終,上訴代碼如下,代碼不完整,請各位自行補全:
1 //角色移動 2 void SmoothMove() 3 { 4 Vector3[] vector3s = _transDataList;// CurvePath.PathControlPointGenerator(_transDataList); 5 int sample = _transDataList.Length * SampleRate; 6 7 _movePtg += Time.deltaTime * MoveSpeed; 8 9 //曲線插值 10 transform.position = CurvePath.Interp(vector3s, _movePtg / sample); 11 12 //計算當前位置到下一個坐標點的向量 13 var vector = (transform.position - _prevPos).normalized; 14 //取得向量的方向 15 var rotation = Quaternion.LookRotation(vector, Vector3.right).eulerAngles; 16 //去處x和z方向的影響,僅作用y方向偏轉 17 rotation.x = 0; 18 rotation.z = 0; 19 20 //將物體旋轉到指向下一個坐標點的方向 21 transform.rotation = Quaternion.Euler(rotation); 22 23 24 _prevPos = transform.position; 25 if (_movePtg >= sample) 26 { 27 ResetLocalData(); 28 } 29 } 30 31 //相機跟隨 32 void FollowCamera() 33 { 34 if (CameraGo == null) return; 35 36 if(UseFollow != 0) 37 { 38 //相機的俯仰角和偏航角,Y方向偏航和目標對象一致 39 Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y + Slider, 0); 40 41 //給向量賦予旋轉 42 var distanceVector = ro * Vector3.forward * Distance; 43 var pos = transform.position - distanceVector; 44 CameraGo.transform.position = pos; 45 CameraGo.transform.rotation = ro; 46 return; 47 } 48 }
unity3D:遊戲分解之角色移動和相機跟隨