Unity3D第三人稱攝像機控制腳本


好久沒有敲Blog該。感謝您的留言、注意、私人信件和其他支持,但我似乎沒有辦法繼續自己曾經寫了一篇博客系列,因為我在網上找到有關unity3D太少的內容,U3D相關的文章!。。


第三人稱視角


第三人稱視角是什么?非常easy,CS就是一種第一人稱視角游戲,玩家沒有辦法看到自己的角色形象,僅僅能觀察除開自己之外的游戲內容。第三人稱視角那么就明顯是可以看到玩家所控制的角色的一種視角。


並且大部分游戲的鏡頭不能固定不動,肯定是要尾隨豬腳。能看到豬腳,可是保持一定的高度和距離,這種視角才是最好的。


U3D中使用鏡頭來呈現游戲畫面,一般來說是Main Camera。

官方有一個使用JS書寫的 第三人稱鏡頭尾隨腳本和豬腳控制腳本,可是鑒於U3D的js語法太過於詭異。於是我想自己去搞明確如何來寫一個自己用起來爽的第三人稱鏡頭尾隨腳本。


==去機場接個人,回來再繼續寫==



OK。以下分步驟完畢這個腳本。關於加入豬腳的gameObject 以及加入CharacterController Component這里就不做解釋了,前提是豬腳可以在場景中前后左右上下移動而且不會穿越障礙物然后我們繼續往下寫。

也就是我們的攝像機如今是固定視角,豬腳能夠任意移動和跳躍,如圖:


1.創建一個腳本文件CameraFollow.cs




2.接下來。分析我們最想要的效果:

  a,攝像機保持和豬腳一定的高度差(y軸固定差值)和

b.距離差(x,z軸向量的合量相對固定);

  c,面向豬腳的正前方

先完畢目的a:

//攝像機固定在豬腳上方10米高度
	public float camera_height=10.0f;
	//攝像機離豬腳大概10米的水平距離
	public float camera_distance=10.0f;

	//攝像機和豬腳的transform屬性
	private Transform player;
	private Transform camera;
	// Use this for initialization
	void Start () {
		//初始化
		player=GameObject.FindGameObjectWithTag("Player").transform;
		camera = Camera.main.transform;
	}
	
	// Update is called once per frame
	void Update () {
		//每一幀都改變攝像機的高度
		camera.position = new Vector3 (player.position.x, player.position.y+ camera_height, player.position.z );
	
	}

效果:

我們在腳本中將高度距離兩個變量暴露為public,能夠在Inspector中改動,先改一個大概愜意的高度



眼下我們看不到豬腳,原因是攝像機的位置是取的豬腳的X,Z 。僅僅是Y軸加上固定高度。

所以我們須要計算攝像機的X,Z坐標與豬腳的X,Z坐標是一個什么樣的關系?

假設單純的 取豬腳的X,Z坐標然后分別減去distance,是不行的,這樣我們僅僅有在某一個方向才干正好在豬腳后方


改動update中的賦值語句為:



那么我們執行游戲,選擇到mainCamera,改動他的Y軸旋轉度,直到鏡頭正好時刻在豬腳后方。發現這個角度一直是45°:


所以不難明確,當且僅當攝像機的Y軸偏離45°的時候,x,z各取地平面某一點的值,攝像機的位置在這個x,z坐標基礎上減去一個同樣的值。攝像機能夠正好看到這個點在正中間。


這是為什么?我來畫個圖示意一下:

忽略掉攝像機的高度差。我們的豬腳在點O(α。0,α)

攝像機在O一撇(0,0,0)

要讓攝像機正好看到豬腳在正中間且保持一定距離,那么本來攝像機的正前方是這個坐標系的Z軸正方向,如今改為朝射線O' O方向。那么偏離量非常明顯因為是個正方形的對角線。(這是透視下的正方形),角度為45°。

問題來了,我們難道要一直保持45°去望着豬腳嗎,別忘了我們的攝像機隨時要旋轉保持正對豬腳的。那么這個位置究竟該是多少呢?

我們 先把C完畢:隨時保證面向豬腳的正前方:


加入這兩行代碼之后。我們再看看問題出在哪兒:




非常明顯,攝像機的朝向是與豬腳的正前方朝向一致的,可是位置呢,當切僅當豬腳Y軸旋轉度偏離Z軸正方向45°的時候。位置在豬腳正后方,小於45°偏左,大於45°偏右,180°+45°直接跑到豬腳正前面去了。

所以說,我們想要的情況是:

45°時,x 與z各減去 distance 

180°+45°=225°時。x與z各加上distance

0°的時候,x不變,z-distance/sin45°  (為什么,由於實際上45°時候線段O'O的長度事實上不是distance而是distance/sin45°。看我畫的那個圖。勾股定理)

90°的時候,z不變,x-distance/sin45°

所以事實上我們這里的定義的distance參數名字和他代表的不一樣,實際距離應該是distance/sin45°

所以不難歸納,我們以角度β為變量。得出x與β的函數關系為:

x-=distance*sinβ

z-=distance*cosβ

正好滿足我們上面列的4個條件

因為我們代碼中須要的三角函數參數是弧度而不是角度,所以這里把角度替換為弧度:

x-=distance*sin(β*π/180)

z-=distance*cos(β*π/180)

所以我們的代碼應該改動為:


//看向豬腳
		//camera.LookAt (player);


		//與豬腳的正前方為正前方(僅僅取Y軸的旋轉度)
		camera.eulerAngles =new Vector3(camera.eulerAngles.x,
		                               player.eulerAngles.y,
		                               camera.eulerAngles.z);
		//獲取當前的鏡頭的Y軸旋轉度
		float angle = camera.eulerAngles.y;

		//計算x軸的距離差:
		float deltaX = camera_distance * Mathf.Sin(angle * Mathf.PI /180 );
		float deltaZ = camera_distance * Mathf.Cos (angle * Mathf.PI / 180);



		//每一幀都改變攝像機的高度
		camera.position = new Vector3 (player.position.x-deltaX,
			                              player.position.y+ camera_height,
			                              player.position.z-deltaZ);


這個lookAt已經不須要了,由於我們的鏡頭旋轉到豬腳的正前方而且位置在他的正后方。那么我們鏡頭必定已經在看他了

最后的效果是不管豬腳如何走。我們的鏡頭都在完美地尾隨:







完整腳本代碼(比官方的樣例精簡吧):

using UnityEngine;
using System.Collections;

//加入腳本到component菜單
[AddComponentMenu ("CameraControl/Follow")]
public class CameraFollow : MonoBehaviour {

	//攝像機固定在豬腳上方10米高度
	public float camera_height=10.0f;
	//攝像機離豬腳大概10米的水平距離
	public float camera_distance=10.0f;

	//攝像機和豬腳的transform屬性
	private Transform player;
	private Transform camera;
	// Use this for initialization
	void Start () {
		//初始化
		player=GameObject.FindGameObjectWithTag("Player").transform;
		camera = Camera.main.transform;
	}
	
	// Update is called once per frame
	void Update () {


		//看向豬腳
		//camera.LookAt (player);


		//與豬腳的正前方為正前方(僅僅取Y軸的旋轉度)
		camera.eulerAngles =new Vector3(camera.eulerAngles.x,
		                               player.eulerAngles.y,
		                               camera.eulerAngles.z);
		//獲取當前的鏡頭的Y軸旋轉度
		float angle = camera.eulerAngles.y;

		//計算x軸的距離差:
		float deltaX = camera_distance * Mathf.Sin(angle * Mathf.PI /180 );
		float deltaZ = camera_distance * Mathf.Cos (angle * Mathf.PI / 180);



		//每一幀都改變攝像機的高度
		camera.position = new Vector3 (player.position.x-deltaX,
			                              player.position.y+ camera_height,
			                              player.position.z-deltaZ);

		Debug.Log("angle:"+angle+",deltax:"+deltaX+",deltaZ:"+deltaZ);

		

	
	}
}


版權聲明:本文博客原創文章,博客,未經同意,不得轉載。


免責聲明!

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



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