1. 程式人生 > >Unity入門:第一個遊戲

Unity入門:第一個遊戲

Unity官網提供了詳盡的文件和豐富的教學視訊,昨天跟著視訊做了一個簡單的3d遊戲“roll-a-ball”。遊戲涉及了許多Unity的基本知識,用來入門很不錯。

這篇博文並不講述整個遊戲的製作流程,如果您感興趣,可以訪問這裡,如果訪問遇到什麼困難,在B站有一摸一樣的視訊

這是完成以後的樣子:


執行效果:


作為個人小結,下面寫一些做這個遊戲的收穫:

1、什麼是Unity?

一款遊戲引擎,至於什麼是遊戲引擎,這裡不展開。

2、下載和安裝

作為學習用途,下載personal版即可。

3、熟悉Unity介面

進入Unity後,將會看到這樣的介面:


上圖將介面劃分成了5部分,下面分別解釋每部分的功能:

(1)Toolbar

上面的按鈕有不同的功能,比如左側的第一個按鈕可以用來移動場景中的物體,第二個按鈕用來進行平移變換,第三個按鈕用來進行旋轉變換等。

(2)Hierarchy window

顧名思義,這個部分顯示的是“層次結構”,場景中的物件都會被列到這個視窗中。當我們新建一個Unity專案時,Unity就會自動為我們新增兩個東西:Main Camera和Directional Light,一個是相機,一個是光照。Hierarchy window上面有一個create按鈕,點選這個按鈕,我們可以看到一個包含了空物件、2d,3d物件、UI、光照、相機等在內的選單,在這裡你可以點選你想建立的東西。

(3)Scene view

這是遊戲的場景,我們可以通過調整右上角的座標系圖案來調整觀察場景的位置。

(4)Inspector window

當我們選中一個物件,開啟Inspector window,這個物件的資訊,例如所在的位置,平移了多少等等都會在這個視窗顯示,當然也可以用這個視窗來調整場景中的物件,例如為了編輯方便,一開始我們會使用transform中的reset,將物件放置在座標原點(0,0,0)。Inspector window最下面有一個Add Component按鈕,通過這個按鈕可以給物件增加其它的component,例如新增一條C#指令碼等。

(5)Project window

這個視窗顯示的是這個遊戲使用的資源,通常我們會在這裡建立一些資料夾,例如Scenes資料夾專門儲存場景,Materials資料夾專門儲存材質,Scripts資料夾專門儲存指令碼等。Project window上有一個不起眼的create按鈕,這個按鈕很有用,例如我們可以點選create->folder來新建一個資料夾等等。

事實上,這只是Unity介面一個最基本的佈局,你可以自己拖動這些window或者view來將它們放置在自己喜歡的位置,也就是說,操作介面是可以個性化的。其實上面漏掉了一個很重要的view:game view,如下圖所示:


這個view的按鈕就在scene view旁邊,上圖中我已經將它拖動到了scene view下面,這個檢視顯示的是我們的遊戲最終呈現給使用者的樣子,製作好一個遊戲後,可以點選Toolbar中間那個表示Play的按鈕進行試玩,遊戲的執行情況就顯示在這個檢視中。

為了方便編輯,我們常把Scene view和Game view並列在一起,就像上圖一樣,這樣,在用Play試玩除錯的時候可以不用頻繁切換檢視,從而節省了時間。

4、怎麼理解遊戲中的幾個指令碼?

Unity會自動為每個新建的C#指令碼生成void Start()和void Update()兩個方法,第一個在第一幀,也就是遊戲剛開始時呼叫,第二個在畫面更新時呼叫(準確地說是在渲染每一幀之前被呼叫)。

在這個遊戲中我們會用到三個指令碼:

(1)CameraController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour {
	public GameObject player;
	private Vector3 offset;

	void Start () {
		offset = transform.position - player.transform.position;
	}
	
	void LateUpdate () {
		transform.position = player.transform.position + offset;
	}
}
指令碼的作用是當Player移動時,讓相機也隨著移動。

這裡有一個問題:要達到類似的效果,為什麼不直接把Main Camera設定成Player的孩子?

(2)PlayerController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PlayerController : MonoBehaviour {
	public float speed;
	public Text countText;
	public Text winText;

	private Rigidbody rb;
	private int count;


	void Start()
	{
		rb = GetComponent<Rigidbody>();
		count = 0;
		SetCountText();
		winText.text = "";
	}

	void FixedUpdate()
	{
		float moveHorizontal = Input.GetAxis("Horizontal");
		float moveVertical = Input.GetAxis("Vertical");
		Vector3 movement=new Vector3(moveHorizontal,0.0f,moveVertical);
		rb.AddForce (movement*speed);
	}

	void OnTriggerEnter(Collider other)
	{
		if (other.gameObject.CompareTag ("PickUp")) 
		{
			other.gameObject.SetActive (false);
			count++;
			SetCountText();
		}	
	}

	void SetCountText()
	{
		countText.text = "Count:" + count.ToString ();
		if(count>=12)
		{
			winText.text="You Win!";
		}
	}
}

這個指令碼被新增到了叫做Player的小球上,Start函式用來做初始化,其中的getComponent用來獲取剛體物件,也就是新增到叫做Player的小球上的那個RigidBody。為什麼用FixedUpdate()不用Update()?因為FixedUpdate在做物理計算之前被呼叫,這個遊戲中的碰撞屬於physics的範疇,所以用FixedUpdate()。還有一個要注意的函式是OnTriggerEnter(),這個函式在物件碰到collider的時候會被觸發,在這個例子中,我們給12個Pickup關聯上了一個叫“PickUp”的Tag,當碰撞發生時如果發現Tag是PickUp,就deactivate這個PickUp(每個PickUp的is trigger需要勾選上)。教學視訊中提到一個問題:除了要給PickUp的collider勾選is trigger,還要加上rigidbody(is kinematic),這是因為Unity計算所有collider的體積後把它們放在一個cache裡,如果collier是靜態的(static),這樣做可以避免在每幀更新的時候重複計算,但是在我們這個遊戲中,因為每次collider都在旋轉,所以每次它的體積都會被重複計算,為了節省資源,可以把collider設定成動態的(dynamic=collider+rigidbody)。

(3)Rotater.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rotator : MonoBehaviour {

	
	// Update is called once per frame
	void Update () {
		transform.Rotate (new Vector3(15,30,45)*Time.deltaTime);
	}
}
這裡要用的是Update而不是FixedUpdate(和物理無關)。

5、其他

(1)prefab

類似模板一樣,可以將需要複用某個邏輯的一堆物件放到prefab資料夾中,這就可以對整體進行編輯、修改了。

(2)快捷鍵

例如ctrl+D用來duplicate

(3)有不懂的查文件!!!