unity遊戲程式設計(05) 2d移動與碰撞處理ii
TRANSCRIPT
電子工程系應 用 電 子 組電 腦 遊 戲 設 計 組
Unity遊戲程式設計(05) 2D移動與碰撞處理II
吳錫修
Oct 24, 2016
shap
e th
e fu
ture
遊戲世界裡必須透過碰撞器來模擬現實世界的物體碰撞情形
碰撞器是在元件加入⼀層透明的偵測層,代表元件物理效應發⽣的範圍
選單命令Component>Physics 2D內可找到所有碰撞器
Rigidbody 2D (剛體)
具備物理性質:摩擦力 (Mass)、線性阻力 ( Linear Drag)、旋轉阻力(Angular Drag)、重力 (Gravity Scale)
剛體會被碰撞器阻擋
IsKinematic屬性
設定為運動物件,本身不受重力影響
埸景中的活動物件都應使用剛體來實現
剛體、碰撞器與觸發器 1/3
2 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
碰撞器
Box Collider 2D (方框碰撞器)
適用於矩形物件上
Circle Collider 2D (圓形碰撞器)
適用於球形物件上
Edge Collider 2D (邊緣碰撞器)
適用於邊界、地板或天花板
可編輯/調整線段節點
Polygon Collider 2D (多邊形碰撞器)
能較精準貼近不規則物件,但會耗用較多運算資源
剛體、碰撞器與觸發器 2/3
3 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
觸發器
當碰撞器被設定Is Trigger屬性,即成為觸發器
剛體物件可以穿透觸發器物件,但支援碰撞偵測
剛體物件之程式腳本必須實作OnTriggerXXX2D函式來處理碰撞作業
void OnTriggerEnter2D(Collider2D other) {//進入碰撞時
}void OnTriggerStay2D(Collider2D other) {//在碰撞物上時
}
void OnTriggerExit2D(Collider2D other) {//結束碰撞時
}
剛體、碰撞器與觸發器 3/3
4 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
在Update()中控制物件移動
更新座標方式 (自行計算位移,物體移動⽣硬不自然)
transform.Translate(Vector3.up * 0.1f);transform.Translate(Vector3.down * 0.1f);transform.Translate(Vector3.right * 0.1f);transform.Translate(Vector3.left * 0.1f);
對剛體物件施力,由物理引擎處理剛體物件移動
_rigidbody2D = this.GetComponent<Rigidbody2D>();
Vector2 force2D = Vector2.zero;force2D.y += forceValue;// force2D.x += forceValue; _rigidbody2D.AddForce(force2D);
物件移動控制
5 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
預設場景上的物件都是放置在Default圖層
Layer屬性是用來做碰撞管理
Sorting Layer是2D遊戲物體前後層次管理
同圖層物件則依Order in Layer值,數值較大者在上層, 若Order in Layer值相同時依Position Z值 (與Main Camera遠近)
遊戲圖層及碰撞管理 1/4
Wu, ShyiShiou Dept. of E.E., NKUT6
shap
e th
e fu
ture
管理圖層
選單命令Edit>Project Settings>Tags and Layers來管理圖層
在Sorting Layers增加Background、Interactive、Player圖層
遊戲圖層及碰撞管理 2/4
下層
上層
Wu, ShyiShiou Dept. of E.E., NKUT7
新增圖層
shap
e th
e fu
ture
將在Sorting Layers中加入的圖層,同步更新到Layers中
遊戲圖層及碰撞管理 3/4
8 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
碰撞管理
選單命令Edit>Project Settings>Physics 2D進行碰撞管理
設定Layer Collision Matrix
預設全部圖層間都會進行碰撞檢測處理
依據遊戲設計需求,設定圖層碰撞檢核
遊戲圖層及碰撞管理 4/4
9 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
冒險家可左、右移動及跳躍
冒險家接觸到毒霧會受傷
冒險家靠近寶箱時會顯示提示箭頭,此時按空白鍵可開啟寶箱
探險遊戲設計 1/2
10 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
新增2D遊戲專案
將預設場景以adventure名稱存檔
將floor.png、trap0.png、trap1.png、trap2.png、tresure0.png、treasure1.png、up.png及主角分鏡素材滙入到專案Assets\Sprite資料夾
Main Camera
Size設定為16
Background設定為深藍色
探險遊戲設計 2/2
11 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
選單命令Edit>Project Settings>Tags and Layers
在Sorting Layers增加Background、Interactive、Player圖層
在Layers加入Background、Interactive、Player圖層
建立遊戲圖層
12 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
將floor拖曳到場景
Position設定為 (x, y, z) = (0, -8, 0)
Scale設定為 (x, y, z) = (2.5, 0.2, 1)
Sorting Layer設定為"Interactive"
Layer設定為"Interactive"
設定碰撞器
在floor加入 Edge Collider 20邊緣碰撞器
選單命令Component>Physics 2D>Edge Collider 2D
建造地板
13 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
下載主角素材 http://gameart.eu.org/files/adventure_girl.zip
將Assets\Sprite\idle1拖曳到場景
命名為girl
Position設定為 (x, y, z) = (-16, -5, 0)
Sorting Layer設定為"Player"
Layer設定為"Player"
加入剛體性質
選單命令Component>Physics 2D>Rigidbody 2D
加入圓形碰撞器
選單命令Component>Physics 2D>Circle Collider 2D
Radius = 2.5,Offset X = -0.5
建立主角
14 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
選取girl物件
選單命令Window>Animation開啟動畫編輯器,使用girl分鏡素材建立以下動畫
建立girl_idle動畫
建立girl_walk動畫
建立girl_jump動畫
建立主角動畫
15 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
選取girl物件
選單命令Window>Animator開啟Animator編輯器
建立⼀個名為act的Int參數
設定girl_idlegirl_walk動作狀態切換條件
取消Has Exit Time
Settings/Transtion Duration設為0
在Consitions中新增act Equals 1
設定girl_idlegirl_jump動作狀態切換條件
取消Has Exit Time
Settings/Transtion Duration設為0
在Consitions中新增act Equals 2
設定主角動畫狀態切換控制 1/2
16 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
設定其它狀態girl_idle動作狀態切換條件
勾選Has Exit Time
Settings/Exit Time設定為1
Settings/Transtion Duration設為0
設定主角動畫狀態切換控制 2/2
17 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
將Assets\Sprite\trap0拖曳到場景
命名為trap
Position設定為 (x, y, z) = (6, -6, 0)
Scale設定為 (x, y, z) = (0.8, 0.8, 1)
Sorting Layer設定為"Interactive"
Layer設定為"Interactive"
在Tag欄新增"trap"標籤
製作陷阱道具 1/2
18 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
在trap物件加入方框碰撞器
選取trap物件
選單命令Component>Physics 2D>Circle Collider 2D
勾選「Is Trigger」屬性 (會偵測物體碰接,但允許剛體物件穿過)
Offset Y=-2.2,讓碰撞邊界比貼近陷阱外緣
製作陷阱道具 2/2
19 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
選取trap物件
選單命令Window>Animation開啟動畫編輯器,使用trap分鏡素材建立以下動畫
建立trap動畫
製作陷阱道具動畫
20 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
將Assets\Sprite\treasures0拖曳到場景
命名為treasure
Position設定為 (x, y, z) = (21, -6, 0)
Scale設定為 (x, y, z) = (0.6, 0.6, 1)
Sorting Layer設定為"Interactive"
Layer設定為"Interactive"
在Tag欄新增"treasure"標籤
製作寶箱道具 1/6
21 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
在treasure物件加入方框碰撞器
選取treasure物件
Component->Physics 2D->Box Collider 2D
勾選「Is Trigger」屬性
將up素材拖曳到treasure物件上,做為treasure的子物件
命名為up
Position設定為 (x, y, z) = (0, 6.5, 0)
製作寶箱道具 2/6
22 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
在treasure物件加入TreasureControl程式腳本
public class TreasureControl : MonoBehaviour {public Sprite open; //寶箱已開啟之Sprite圖片public bool isOpen; //寶箱狀態private bool _isShow = false; //指示箭頭顯示旗號private float _alpha = 0.0f;private float _da = -0.01f;private GameObject _prompt;private SpriteRenderer _upSprite;
void Awake () {_prompt=GameObject.Find("up"); //指示箭頭物件參照_prompt.gameObject.SetActive (_isShow); //隱藏指示箭頭
}
void Start () {_upSprite = _prompt.GetComponent<SpriteRenderer> ();
}
製作寶箱道具 3/6
23 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
// Update is called once per framevoid Update () {if (isOpen) { //寶箱已被開啟this.GetComponent<SpriteRenderer> ().sprite = open;_prompt.gameObject.SetActive (false); //隱藏指示箭頭
} else {if (_isShow) {_alpha += _da; //使指示箭頭淡入淡出動態顯示_upSprite.material.color = new Color (1f, 1f, 1f, _alpha);if (_alpha>1.0f || _alpha<0.0f) _da = -_da;
}}
}
製作寶箱道具 4/6
24 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
//玩家到達寶箱位置void OnTriggerEnter2D(Collider2D c) {if (c.gameObject.name == "girl") {_isShow = true;_prompt.gameObject.SetActive (_isShow); //顯示指示箭頭
}}
//玩家離開寶箱位置void OnTriggerExit2D(Collider2D c) {if (c.gameObject.name == "girl") {_isShow = false;_prompt.gameObject.SetActive (_isShow); //隱藏指示箭頭_alpha = 0.0f;
}}
}
製作寶箱道具 5/6
25 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
將Assets\Sprite\treasures1素材(寶箱開啟圖片)拖曳到寶箱之Treasure Control下的Open屬性
製作寶箱道具 6/6
26 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
在girl物件加入GirlControl程式腳本
public class GirlControl : MonoBehaviour {private Animator _animator; //主角動畫控制器public float speed = 10f; //主角移動速度private float _alpha = 0.0f;private float _da = -0.1f;private SpriteRenderer _playerSprite;private bool _isInjure = false; //主角跳躍旗號private bool _isJump = false; //主角跳躍旗號
// Use this for initializationvoid Start () {_animator = this.GetComponent<Animator> ();_playerSprite = this.GetComponent<SpriteRenderer> ();
}
設計主角程式腳本 1/5
27 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
//動畫撥放副程式private void PlayAnimation(int action){_animator.SetInteger ("act", action);
}
// Update is called once per framevoid Update () {if (Input.GetKey (KeyCode.RightArrow)) {this.transform.eulerAngles = Vector3.zero; //使主角面向右this.transform.Translate (speed * Time.deltaTime, 0, 0); //主角向右移動if (!_isJump) PlayAnimation (2); //跑步動畫
}else if (Input.GetKey (KeyCode.LeftArrow)) {this.transform.eulerAngles = new Vector3 (0, 180, 0); //使主角面向左this.transform.Translate (speed * Time.deltaTime, 0, 0); //主角向左移動if (!_isJump) PlayAnimation (2); //跑步動畫
}
設計主角程式腳本 2/5
28 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
else if (Input.GetKey (KeyCode.UpArrow)) {if (!_isJump) {this.GetComponent<Rigidbody2D> ().AddForce (Vector2.up * 500);_isJump = true; //主角為跳躍狀態PlayAnimation (1); //跳躍動畫
}}else if (!_isJump) {PlayAnimation (0);
}
if (_isInjure) { //顯示主角受傷效果_alpha += _da;_playerSprite.material.color = new Color (1f, 1f, 1f, _alpha);if (_alpha > 1.0f || _alpha < 0.0f) _da = -_da;
}}
設計主角程式腳本 3/5
29 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
void OnTriggerEnter2D(Collider2D c) {if (c.gameObject.tag == "trap") { //主角碰到陷阱_isInjure = true; //主角為受傷狀態
}}
void OnTriggerExit2D(Collider2D c) {if (c.gameObject.name == "trap") { //主角脫離陷阱_isInjure = false; //主角為正常狀態_playerSprite.material.color = new Color (1f, 1f, 1f, 1f);
}}
設計主角程式腳本 4/5
30 Wu, ShyiShiou Dept. of E.E., NKUT
shap
e th
e fu
ture
void OnTriggerStay2D (Collider2D c) {if (c.gameObject.tag == "treasure") { //主角在寶箱處if (Input.GetKeyDown (KeyCode.Space)) { //按空白鍵取得寶藏c.gameObject.GetComponent<TreasureControl>().isOpen=true;
}}
}
void OnCollisionEnter2D(Collision2D c) {if (c.gameObject.name == "floor") { //主角接觸地板_isJump = false;
}}
}
設計主角程式腳本 5/5
31 Wu, ShyiShiou Dept. of E.E., NKUT