unity案例入門(二)(坦克大戰)


1. 案例簡述

這個案例實現一個簡單的坦克對戰游戲,兩個玩家在一個地圖上PK。

2. 控制坦克移動

與案例一中小球的移動方式不同,坦克在橫向上不能是平移,因此橫向按鍵控制的應該是坦克旋轉。

public float speed = 5;//前進速度
public float angularSpeed = 5;//旋轉速度
private Rigidbody rd;

void Start () {
	rd = this.GetComponent<Rigidbody> ();
}

void FixedUpdate(){
	float v = Input.GetAxis ("VerticalPlayer" + number);//自定義虛擬軸
	rd.velocity = transform.forward * v * speed;//根據情況需要在剛體組件Constraints凍結相應position或rotation

	float h = Input.GetAxis ("HorizontalPlayer" + number);
	rd.angularVelocity = transform.up * h * angularSpeed;
}

(1)與Update()不同,Update()方法是游戲每渲染一幀調用一次,調用的頻率會受機器影響,而FixedUpdate()是每隔一定時間間隔調用一次,調用的頻率不受機器影響。因此,為了得到更逼真的物理效果,在模擬物理運動時,一般選擇在FixedUpdate()中。

(2)由於游戲中有兩個玩家,asdw和方向鍵需要控制兩個不同角色,因此需要自定義虛擬軸,位置是:Edit->Project Setting->Input。

(3)根據實際情況,需要在剛體組件中的Constraints進行相應的Freeze操作。

3. 控制子彈發射

public class TankAttack : MonoBehaviour {

	public GameObject shellPrefab;//子彈的預設
	public KeyCode fireKey = KeyCode.Space;//發射子彈的按鍵
	public float shellSpeed = 15;//子彈射出速度
	private Transform firePosition;//發射子彈的位置

	void Start () {
		firePosition = transform.Find ("FirePosition");
	}
	
	void Update () {
		if (Input.GetKeyDown(fireKey)) {
			GameObject go = GameObject.Instantiate (shellPrefab, firePosition.position, firePosition.rotation) as GameObject;//生成子彈
			go.GetComponent<Rigidbody> ().velocity = go.transform.forward * shellSpeed;//發射子彈
		}
	}
}

生成子彈的位置是坦克炮筒處,因此在該處新建一個空對象,調整其旋轉角度,這個對象的transform即可作為生成子彈的transform。

public class Shell : MonoBehaviour {

	public GameObject shellExplosionPrefab;

	...

	void OnCollisionEnter(Collision collision){
		GameObject.Instantiate (shellExplosionPrefab, transform.position, transform.rotation);
		GameObject.Destroy (this.gameObject);//若傳入參數為this,則值銷毀當前腳本而非游戲對象
	}
}

對子彈進行碰撞檢測(觸發檢測也可以,區別在於爆炸前有無撞擊效果),當子彈擊中物體時即在當前位置生成爆炸特效,同時銷毀子彈對象。

public class DestroyForTime : MonoBehaviour {

	public float time;//在檢視面板傳入該特效的播放時長

	void Start () {
		Destroy (this.gameObject, time);//播放完畢后銷毀
	}
}

給爆炸特效增加腳本,當特效播放完畢后銷毀對象。

4. 子彈擊中坦克產生傷害

在子彈擊中坦克后,主要處理在坦克的生命值上,因此在子彈的碰撞檢測中發送消息,而后在坦克中進行處理。

if (collision.collider.tag == "Tank") {
	collision.collider.SendMessage ("TakeDamage");//若擊中坦克,則發送消息
}

給坦克增加一個單獨的腳本進行生命值的控制:

public class TankHealth : MonoBehaviour {

	public GameObject tankExposionPrefab;
	public int health = 100;

	void TakeDamage(){
		health -= Random.Range (10, 20);
		if (health <= 0) {
			GameObject.Instantiate (tankExposionPrefab, this.transform.position, this.transform.rotation);
			GameObject.Destroy (this.gameObject);
		}
	}
}

5. 雙主角的情況下控制相機跟隨、視野縮放

public class FollowTarget : MonoBehaviour {

	public Transform player1;
	public Transform player2;

	private Camera camera;
	private Vector3 offset;

	void Start () {
		camera = this.GetComponent<Camera> ();
		offset = transform.position - (player1.position + player2.position) / 2;
	}
	
	void Update () {
		transform.position = (player1.position + player2.position) / 2 + offset;
		float distance = Vector3.Distance (player1.position, player2.position);
		float size = distance;
		camera.orthographicSize = size;//讓正交相機視野實時改變
	}
}

(1)雙角色的相機跟隨本質上與單角色沒太大區別,只是將視點定在兩個角色的中心點,通過中心點計算相機的偏移量,實時更新相機的position。

(2)視野的縮放則是利用了正交相機的size與兩個角色之間的距離之比進行更改,案例中兩角色之間初始距離為10,相機size為10,因此比例為1,所以直接讓size = distance。

6. 控制聲音播放

AudioSource.PlayClipAtPoint (tankExposionAudio, this.transform.position);

第一種方法,播放獲得的AudioClip對象,第一個參數為AudioClip對象,第二個參數為播放位置。

第二種方法,為游戲對象添加一個AudioSource組件,在腳本中通過GetComponent()方法獲得該組件,調用其play()方法進行播放。

案例下載 密碼:z79o


免責聲明!

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



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