Unity 3d 實現物體跟隨攝像機視野運動


https://blog.csdn.net/qq_31411825/article/details/61623857

 

Unity 3d 實現物體跟隨攝像機視野運動
Created by miccall (轉載請注明出處 miccall.tech )
1. VR實現機器人導航
-
項目里要求一個機器人跟隨在角色旁邊,一直飛着,就像一個精靈一樣,總在主角的身邊,移動,轉頭,都要移動到合適的位置 。還得讓他面向主角,今天就來實現這個樣例 。
-

2. 問題思考
- 1. 物體移動到某個給定的位置(target)
- 2. 物體轉動到面向攝像機
- 3. 出現在相機的視野當中
- 4. 自定義物體在攝影機的Screen中的位置

3.實現以及方法
-
移動的話 ,本來可以用動畫來實現 ,因為動畫還沒有做好,我就用一個cube當作那個機器人做樣例了 。
首先有個cube之后 ,給他放一個移動的腳本。這里我給他命名為PlayerTank 。
我們的目的就是讓他運動到某個target ,所以我們得給他指定一個followTransform 。 同時還有他的移動速度和轉動速度 。
為了使他移動不是很突兀,我的思路是他先轉動到面向follow物體,然后在直線移動到給物體 。所以算法很快寫好了 。


void LookTransform(Transform Mtransform)
{
Vector3 tarPos = Mtransform.position;
Vector3 dirRot = tarPos - transform.position;
Quaternion tarRot = Quaternion.LookRotation(dirRot);
transform.rotation = Quaternion.Slerp(transform.rotation, tarRot, rotSpeed * Time.deltaTime);
}

-
簡單解釋一下,就是先確定物體的位置,然后求出指向他的方向,並用插值的方法,讓物體轉動到面向指定的物體 。
好了,既然有了朝向的運動方向,那么走到這方向,就很簡單了。
-

transform.Translate(new Vector3(0, 0, movementSpeed * Time.deltaTime));
1
-
那么什么時候停止運動呢 ,我想了一下,決定用位置的差來判斷
就是
-

Vector3.Distance(transform.position, followTransform.position);
1
-
好了,既然停止的方法也有了,最后要解決的問題就是朝向攝像機了。
突然一想,這是問題么,對,這不是問題 ,哈哈,剛剛寫的那個算法,給一個攝像機就解決了嘛 。
然后給出具體的判斷邏輯 。
-

//該物體 接近要 到達的目標 指定位置后就停止
if (Vector3.Distance(transform.position, followTransform.position) < 3f)
{
//當物體道到位置時 讓物體面 向攝像機
LookTransform(Camre);
return;
}
else
{
//讓物體轉向 將要運動 的方向
LookTransform(followTransform);
transform.Translate(new Vector3(0, 0, movementSpeed * Time.deltaTime));
}

-
這樣就解決了物體移動到target了,下一步就是固定target的位置,讓他在攝像機的固定位置了 。
新建一個腳本文件CameraView,掛在攝像機上。為了方便調試,我又用了FPS腳本,就是第一人稱視角跟隨鼠標轉動,就跟cs里面的玩法一樣,(百度一大推代碼)。
第二個調試算法是一個國外大牛寫的 ,他可以給定一個距離,畫出攝像機的視野范圍
-


-
這里我畫了兩個邊 ,一個是距離攝像機8.5米 用黃色表示,距離攝像機12米的用紅色表示。
應為篇幅問題和詳略問題,這里不多解釋這個算法,有興趣的可以去研究一下,這里我們引用一下就行了。
-

Vector3[] GetCorners(float distance)
{
Vector3[] corners = new Vector3[4];

float halfFOV = (theCamera.fieldOfView * 0.5f) * Mathf.Deg2Rad;
float aspect = theCamera.aspect;

float height = distance * Mathf.Tan(halfFOV);
float width = height * aspect;

// UpperLeft
corners[0] = tx.position - (tx.right * width);
corners[0] += tx.up * height;
corners[0] += tx.forward * distance;

// UpperRight
corners[1] = tx.position + (tx.right * width);
corners[1] += tx.up * height;
corners[1] += tx.forward * distance;

// LowerLeft
corners[2] = tx.position - (tx.right * width);
corners[2] -= tx.up * height;
corners[2] += tx.forward * distance;

// LowerRight
corners[3] = tx.position + (tx.right * width);
corners[3] -= tx.up * height;
corners[3] += tx.forward * distance;

return corners;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void FindUpperCorners()
{
Vector3[] corners = GetCorners(upperDistance);
// for debugging
Debug.DrawLine(corners[0], corners[1], Color.yellow); // UpperLeft -> UpperRight
Debug.DrawLine(corners[1], corners[3], Color.yellow); // UpperRight -> LowerRight
Debug.DrawLine(corners[3], corners[2], Color.yellow); // LowerRight -> LowerLeft
Debug.DrawLine(corners[2], corners[0], Color.yellow); // LowerLeft -> UpperLeft
}
1
2
3
4
5
6
7
8
9
-
debug的時候,直接調用FindUpperCorners()就可以了 。
剛開始的時候 ,我就用的這個調試 ,給出一個位置,然后計算他的偏移量,調試了很久,沒有一個良好的效果,我決定換個思路了 ,為了普遍大眾 ,我還是把這個調試方法貼出來了,有需要的可以試試 。
第二個我就去翻api了 ,因為我貌似記得有個屏幕坐標和世界坐標轉化的什么鬼方法來着。果然不出我所料,這個方法的確是相當的好用的呀 。
試了一下官方給的調試方法,畫了一個點出來 。
-
1
2
3
4
5
6
void OnDrawGizmosSelected()
{
Vector3 p = theCamera.ScreenToWorldPoint(new Vector3(100, 200, 8));
Gizmos.color = Color.blue;
//target.position = p;
Gizmos.DrawSphere(p, 1F);
}
1
2
3
4
5
6
7
-
好了,就連我最后決定用的位置也標明了。
然后,我就寫了一個很簡單的方法來達到目的。
-
1
2
3
4
void maketarget()
{
Vector3 p = theCamera.ScreenToWorldPoint(new Vector3(RH, RV, upperDistance));
target.position = p;
}
1
2
3
4
5
-
寫完我都嚇了一跳 ,竟然如此簡單。還是簡單解釋一下 ,RH 是水平偏移量,RV是垂直偏移量,upperDistance是距離攝像機的一個平面位置 。
接下來就是運行看效果了 。
-
1
2
3
4
4.中途出現的小BUG
-
莫名其妙的做圓周運動 ,然后我分析了線速度,角速度和半徑的關系 ,然后總結出一個基本的規律,他應該是當運動到某個特定的位置 ,正好滿足了圓周運動的關系,然后我們調整movementSpeed 和rotSpeed 的值,讓他么盡可能的和Distance消除乘積關系,這樣出現的幾率就微乎其微了 。
感想 -- 其實unity和現實物理,理論物理 還是有很大的不同。
-
————————————————
版權聲明:本文為CSDN博主「miccall」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_31411825/article/details/61623857


免責聲明!

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



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