SlideShare a Scribd company logo
1 of 64
Download to read offline
2D Platformer遊戲
Revised on January 1, 2020
 背景動畫與背景音樂
 玩家角色控制
 隨機生成敵人
 空投道具
 使用道具
 顯示分數
 暫停遊戲控制
 建立2D專案,my2DPlatformer
 選單命令File> Save As…,將預設場景另存新檔
 Exercise.unity
 調整Main Camera
 Position(X, Y, Z) = (-4.43, -0.15, -10)
 Background(R, G, B, A) = (163, 187, 196, 5)
 Size = 11
 Free Aspect
 滙入遊戲資源
 選單命令Assets> Import Package> Custom Package…,滙入
platformer2d.unitypackage
建立專案 1/3
2
 新增Tags
 ground、Crate、Enemy、Wall、Obstacle、
Bullet、BombPickup、ExplosionFX、
HealthBar
 新增Sorting Layers (遊戲圖層)
 Background、Character、Foreground、UI
 新增Layers (碰撞管理圖層)
 Bombs、Player、Enemies、Pickups、
Ground
建立專案 2/3
3
 選單命令Edit> Project Settings…
 Physics 2D Layer Collicion Matrix
建立專案 3/3
4
 將Assets/Prefebs/Environment/backgrounds.prefab加到場景
 Sorting Layer = Background
 設定所有子物件Sorting Layer = Background
 將Assets/Prefabs/Environment/Foregrounds.prefab加到場景
 設定所有子物件Sorting Layer = Foreground
建立場景
5
 選取Prefabs/Props/swan.prefab
 Sorting Layer = Background
 選取Prefabs/Environment/Cab.prefab
 Sorting Layer = Background
 Wheels子物件
 Sorting Layer = Background
 選取Prefabs/Environment/Bus.prefab
 Sorting Layer = Background
 Wheels子物件
 Sorting Layer = Background
設定背景動畫預製物件
6
 在_Scripts目錄下新增BackgroundPropSpawner.cs程式腳本
using UnityEngine;
using System.Collections;
public class BackgroundPropSpawner : MonoBehaviour {
public Rigidbody2D backgroundProp; //待生成的背景預製物件
public float leftSpawnPosX; //左側生成位置x座標
public float rightSpawnPosX; //右側生成位置x座標
public float minSpawnPosY; //生成位置y座標區間最小值
public float maxSpawnPosY; //生成位置y座標區間最大值
public float minTimeBetweenSpawns; //生成間隔時間最小值
public float maxTimeBetweenSpawns; //生成間隔時間最大值
public float minSpeed; //最小移動速度
public float maxSpeed; //移動速度最大值
void Start () {
Random.InitState(System.DateTime.Today.Millisecond);
StartCoroutine("Spawn"); //起始Spawn程序
}
隨機產生背景動畫物件 1/6
7
IEnumerator Spawn () {
float waitTime = Random.Range(minTimeBetweenSpawns, maxTimeBetweenSpawns);
yield return new WaitForSeconds(waitTime); //隨機等待一段時間
bool facingLeft = Random.Range(0,2) == 0; //隨機設定預製物件方向
float posX = facingLeft ? rightSpawnPosX : leftSpawnPosX;
float posY = Random.Range(minSpawnPosY, maxSpawnPosY);
Vector3 spawnPos = new Vector3(posX, posY, transform.position.z);
Rigidbody2D propInstance =
Instantiate(backgroundProp, spawnPos, Quaternion.identity) as Rigidbody2D;
if (!facingLeft) {
Vector3 scale = propInstance.transform.localScale;
scale.x *= -1;
propInstance.transform.localScale = scale;
}
float speed = Random.Range(minSpeed, maxSpeed); //隨機設定速度
speed *= facingLeft ? -1f : 1f;
propInstance.velocity = new Vector2(speed, 0);
StartCoroutine(Spawn());
隨機產生背景動畫物件 2/6
8
while (propInstance != null) {
if (facingLeft) {
if (propInstance.transform.position.x < leftSpawnPosX - 0.5f)
Destroy(propInstance.gameObject);
}
else {
if (propInstance.transform.position.x > rightSpawnPosX + 0.5f)
Destroy(propInstance.gameObject);
}
yield return null;
}
}
}
隨機產生背景動畫物件 3/6
9
 新增空物件,命名為swanCreator
 重置Transform
 加入BackgroundPropSpawner.cs程式腳本
 拖曳Prefabs/Props/swan.prefab到Prop欄
 Left Spawn Pos X = -24
 Right Spawn Pos X = 24
 Min Spawn Pos Y = 4
 Max Spawn Pos Y = 8
 Min Time Between Spawns = 2
 Max Time Between Spawns = 8
 Min Speed = 5
 Max Speed = 8
 測試遊戲,天空會隨機有天鵝飛過
隨機產生背景動畫物件 4/6
10
 新增空物件,命名為busCreator
 重置Transform
 加入BackgroundPropSpawner.cs程式腳本
 拖曳Prefabs/Environment/Bus.prefab到Prop欄
 Left Spawn Pos X = -24
 Right Spawn Pos X = 24
 Min Spawn Pos Y = -5.5
 Max Spawn Pos Y = -5.5
 Min Time Between Spawns = 8
 Max Time Between Spawns = 18
 Min Speed = 5
 Max Speed = 8
 測試遊戲,街道會隨機有巴士通過
隨機產生背景動畫物件 5/6
11
 新增空物件,命名為cabCreator
 重置Transform
 加入BackgroundPropSpawner.cs程式腳本
 拖曳Prefabs/Environment/Cab.prefab到Prop欄
 Left Spawn Pos X = -24
 Right Spawn Pos X = 24
 Min Spawn Pos Y = -6.4
 Max Spawn Pos Y = -6.4
 Min Time Between Spawns = 10
 Max Time Between Spawns = 15
 Min Speed = 5
 Max Speed = 8
 測試遊戲,街道會隨機有計程車通過
隨機產生背景動畫物件 6/6
12
 新增空物件,命名為music
 重置Transform
 加入AudioSource元件
 AudioClip = MainTheme
 勾選Play On Awake
 勾選Loop
 Volume = 0.1
 Reverb Zone Mix = 0
 測試專案,遊戲執行時會持續撥放背景音樂
加入背景音樂
13
 將Assets/Prefabs/Chractera/Mr.Bean.prefab加倒場景
 設定所有子物件Sorting Layer = Character
 Tag = Player
 Layer = Player
建立玩家角色
14
 Mr.Bean動作控制器
玩家角色控制 1/5
15
 在Mr.Bean物件加入PlayerControl.cs程式腳本
using UnityEngine;
using System.Collections;
public class PlayerControl : MonoBehaviour {
[HideInInspector]
public bool facingRight = true; //方向旗號,不顯示在屬性窗格,但可提其它程式腳本存取
[HideInInspector]
public bool jump = false; //跳躍旗號,不顯示在屬性窗格,但可提其它程式腳本存取
public float moveForce = 365f; //行進力道
public float maxSpeed = 5f; //移動速度上限
public AudioClip[] jumpClips; //跳躍動作音效庫
public float jumpForce = 1000f; //跳躍力道
private Transform groundCheck; //用來檢查玩家角色是否站在地面
private bool grounded = false; //落地旗號
private Animator anim; //玩家角色動作控制器參照
玩家角色控制 2/5
16
void Awake() {
groundCheck = transform.Find("groundCheck");
anim = GetComponent<Animator>();
}
void Update() {
grounded = Physics2D.Linecast(transform.position,
groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
//玩家角色位於在地面,並按下Jump鍵
if (Input.GetButtonDown("Jump") && grounded)
jump = true; //執行跳躍動作
}
玩家角色控制 3/5
17
void FixedUpdate () {
float h = Input.GetAxis("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(h));
if (h * GetComponent<Rigidbody2D>().velocity.x < maxSpeed)
GetComponent<Rigidbody2D>().AddForce(Vector2.right * h * moveForce); //加速
if (Mathf.Abs(GetComponent<Rigidbody2D>().velocity.x) > maxSpeed)
GetComponent<Rigidbody2D>().velocity =
new Vector2(Mathf.Sign(GetComponent<Rigidbody2D>().velocity.x) * maxSpeed,
GetComponent<Rigidbody2D>().velocity.y);
if (h > 0 && !facingRight) Flip(); //反轉方向
else if (h < 0 && facingRight) Flip(); //反轉方向
if (jump) {
anim.SetTrigger("Jump");
int i = Random.Range(0, jumpClips.Length); //隨機撥放跳躍音效
AudioSource.PlayClipAtPoint(jumpClips[i], transform.position);
GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, jumpForce)); //跳躍
jump = false; //防止重複跳躍
}
}
玩家角色控制 4/5
18
void Flip () {
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
 拖曳Audio/Player/Jumps/Player-
jump[1-3].wav到Jump Clips欄
 測試遊戲,可操控主角移動
 適度調整移動速度及跳躍力道
玩家角色控制 5/5
19
 新增空物件,命名為healthUI
 Tag = HealthBar
 Position(X, Y, Z) = (0, 100, 0)
 在healthUI下新增Sprite物件,命名為HealthBar
 Position(X, Y, Z) = (-0.83, 0, 0)
 拖曳Assets/Sprites/_UI/Health.png到Sprite Renderer之Sprite欄
 拖曳Assets/Materials/Health.mat到Sprite Renderer之Material欄
 Sorting Layer = Foreground
建立玩家生命條 1/4
20
 在healthUI下新增Sprite物件,命名為HealthOutline
 Position(X, Y, Z) = (0, 0, 0)
 拖曳Assets/Sprites/_UI/Health-bg.png到Sprite Renderer之
Sprite欄
 拖曳Assets/Materials/DefaultPixelSnap.mat到Sprite Renderer
之Material欄
 Sorting Layer = Foreground
建立玩家生命條 2/4
21
 在healthUI加入FollowPlayer.cs程式腳本
using UnityEngine;
using System.Collections;
public class FollowPlayer : MonoBehaviour {
public Vector3 offset; //顯示位置偏移值
private Transform player;
void Awake () {
player = GameObject.FindGameObjectWithTag("Player").transform;
}
void Update () {
transform.position = player.position + offset;
}
}
建立玩家生命條 3/4
22
 設定healthUI之FollowPlayer
 Offset(X, Y, Z) = (0, 1.2, 0)
 測試遊戲,玩家角色上方會顯示生命條並且跟隨移動
建立玩家生命條 4/4
23
 在Mr.Bean物件加入PlayerHealth.cs程式腳本
using UnityEngine;
using System.Collections;
public class PlayerHealth : MonoBehaviour {
public float health = 100f; //玩家生命值
public float repeatDamagePeriod = 1f; //玩家連續受傷之時時間隔
public AudioClip[] ouchClips; //玩家受傷音效
public float hurtForce = 100f; //玩家受傷時受到之推力
public float damageAmount = 10f; //每次受傷之損血值
private SpriteRenderer healthBar; //玩家生命條之sprite renderer參照
private float lastHitTime; //前次受傷時間戳記
private Vector3 healthScale; //生命條滿格時之大小
private PlayerControl playerControl; //玩家PlayerControl程式腳本參照
private Animator anim; //玩家動作控制器參照
玩家生命值管理 1/4
24
void Awake () {
playerControl = GetComponent<PlayerControl>(); //玩家PlayerControl參照
healthBar = GameObject.Find("HealthBar").GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>(); //玩家動作控制器參照
healthScale = healthBar.transform.localScale; //記錄生命條滿格之大小
}
void OnCollisionEnter2D (Collision2D col) {
if (col.gameObject.tag == "Enemy") { //敵人撞到玩家
if (Time.time > lastHitTime + repeatDamagePeriod) { //已達連續受傷之時間間隔
if (health > 0f) {
TakeDamage(col.transform); //使玩家損血
lastHitTime = Time.time; //記錄受傷時間
}
else { //玩家死亡,使玩家摔落河裡
Collider2D[] cols = GetComponents<Collider2D>();
foreach (Collider2D c in cols) { //將所有Collider2D調整為觸發器
c.isTrigger = true;
}
SpriteRenderer[] spr = GetComponentsInChildren<SpriteRenderer>();
玩家生命值管理 2/4
25
foreach(SpriteRenderer s in spr) { //將玩家角色移到UI圖層
s.sortingLayerName = "UI";
}
GetComponent<PlayerControl>().enabled = false; //停止PlayerControl程式腳本
GetComponentInChildren<Gun>().enabled = false; //停止Gun程式腳本
anim.SetTrigger("Die"); //觸發Die動畫
}
}
}
}
void TakeDamage (Transform enemy) {
playerControl.jump = false; //停止跳躍
Vector3 hurtVector = transform.position - enemy.position + Vector3.up * 5f;
GetComponent<Rigidbody2D>().AddForce(hurtVector * hurtForce);//向玩家施加衝撞力
health -= damageAmount; //扣減玩家血量
UpdateHealthBar(); //更新顯示生命條
int i = Random.Range (0, ouchClips.Length); //隨機撥放玩家受傷音效
AudioSource.PlayClipAtPoint(ouchClips[i], transform.position);
}
玩家生命值管理 3/4
26
public void UpdateHealthBar () {
//根據玩家的生命值,將生命條的顏色設置為綠色和紅色之間的比例
healthBar.material.color = Color.Lerp(Color.green, Color.red, 1 - health * 0.01f);
//根據玩家的生命值,調整生命條的寬度
healthBar.transform.localScale = new Vector3(healthScale.x * health * 0.01f, 1, 1);
}
}
 拖曳Assets/Audio/Player/Ouch/Player-ouch[1-4].wav到Ouch
Clips欄
玩家生命值管理 4/4
27
攝影機跟隨玩家移動 1/4
28
場景活動範圍
攝影機可視範圍
 在Main Camera加入CameraFollow.cs程式腳本
using UnityEngine;
using System.Collections;
public class CameraFollow : MonoBehaviour {
public float xMargin = 1f; //攝影機啟動跟隨前允許玩家移動的水平位移
public float yMargin = 1f; //攝影機啟動跟隨前允許玩家移動的垂直位移
public float xSmooth = 8f; //使相機平穩地捕捉目標運動之X軸修正值
public float ySmooth = 8f; //使相機平穩地捕捉目標運動之Y軸修正值
public Vector2 maxXAndY; //攝影機位置X與Y座標最大值
public Vector2 minXAndY; //攝影機位置X與Y座標最小值
private Transform player; //玩家角色transform屬性
void Awake () {
player = GameObject.FindGameObjectWithTag("Player").transform;
}
bool CheckXMargin() {
return Mathf.Abs(transform.position.x - player.position.x) > xMargin;
}
攝影機跟隨玩家移動 2/4
29
bool CheckYMargin() {
return Mathf.Abs(transform.position.y - player.position.y) > yMargin;
}
void FixedUpdate () {
TrackPlayer();
}
void TrackPlayer () {
float targetX = transform.position.x;
float targetY = transform.position.y;
if (CheckXMargin())
targetX = Mathf.Lerp(transform.position.x,
player.position.x, xSmooth * Time.deltaTime);
if (CheckYMargin())
targetY = Mathf.Lerp(transform.position.y,
player.position.y, ySmooth * Time.deltaTime);
targetX = Mathf.Clamp(targetX, minXAndY.x, maxXAndY.x);
targetY = Mathf.Clamp(targetY, minXAndY.y, maxXAndY.y);
transform.position = new Vector3(targetX, targetY, transform.position.z);
}
}
攝影機跟隨玩家移動 3/4
30
 設定Camera Follow參數
 X Margin = 2,Y Margin = 2
 X Smooth = 2,Y Smooth = 2
 Max(X, Y) = (5, 5)
 Min(X, Y) = (-5, -5)
 測試遊戲,玩家水平或垂直位移超過2時,攝影機就會自動跟隨
攝影機跟隨玩家移動 4/4
31
 選取Assets/Prefabs/Props/rocket.prefab
 子物件Sorting Layer = Character
 在Mr.Bean的Gun子物件加入Gun.cs腳本
using UnityEngine;
using System.Collections;
public class Gun : MonoBehaviour {
public Rigidbody2D rocket; //rocket預製物件
public float speed = 25f; //rocket速度
private PlayerControl playerCtrl; //PlayerControl程式腳本參照
private Animator anim; //角色動畫控制器參照
void Awake() {
anim = transform.root.gameObject.GetComponent<Animator>();
playerCtrl = transform.root.GetComponent<PlayerControl>();
}
Mr.Bean射擊控制 1/3
32
void Update () {
if (Input.GetButtonDown("Fire1")) { //按下發射鍵
anim.SetTrigger("Shoot");
GetComponent<AudioSource>().Play();
if (playerCtrl.facingRight) { //向右發射
Rigidbody2D bulletInstance = Instantiate(rocket, transform.position,
Quaternion.Euler(new Vector3(0, 0, 0))) as Rigidbody2D;
bulletInstance.velocity = new Vector2(speed, 0);
}
else { //向左發射
Rigidbody2D bulletInstance = Instantiate(rocket, transform.position,
Quaternion.Euler(new Vector3(0, 0, 180f))) as Rigidbody2D;
bulletInstance.velocity = new Vector2(-speed, 0);
}
}
}
}
Mr.Bean射擊控制 2/3
33
 拖曳Assets/Prefabs/Props/rocket.prefab到Gun腳本的Rocket
資料欄
 選取Assets/Prefabs/Props/rocketExplosion.prefab
 Sorting Layer = Foreground
 測試遊戲,點擊滑鼠左鍵可發射火箭彈
Mr.Bean射擊控制 3/3
34
 選單命令GameObject> UI> Text,命名為Score
 Anchor Presets = top, center
 Pos(X, Y, Z) = (0, -10, 0)
 Width = 500, Height = 100
 Pivot(X, Y) = (0.5, 1)
 Text = Score
 Font = BradBunR
 Font Size = 80
 Alignment = Center
 Color = white
加入計分板 1/5
35
 在Score加入Score.cs程式腳本
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Score : MonoBehaviour {
public int score = 0; //玩家分數值
void Update () {
GetComponent<Text>().text = "Score: " + score; //更新顯示分數
}
}
加入計分板 2/5
36
 選單命令GameObject> UI> Text,命名為Score-shadow
 Anchor Presets = top, center
 Pos(X, Y, Z) = (0, -14, 0)
 Width = 500, Height = 100
 Pivot(X, Y) = (0.5, 1)
 Text = Score
 Font = BradBunR
 Font Size = 80
 Alignment = Center
 Color = black
加入計分板 3/5
37
 在Score-shadow加入ScoreShadow.cs程式腳本
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class ScoreShadow : MonoBehaviour {
public GameObject guiCopy; // Score物件參照
void Awake () {
Vector3 behindPos = transform.position;
behindPos = new Vector3(guiCopy.transform.position.x,
guiCopy.transform.position.y - 4f,
guiCopy.transform.position.z);
transform.position = behindPos;
}
void Update () {
GetComponent<Text>().text = guiCopy.GetComponent<Text>().text; //同步更新資料
}
}
加入計分板 4/5
38
 拖曳Score到Score-shadow之Gui Copy欄
 調整Hierarhy窗格中物件順序,使Score位於Score-shadow下方
 測試遊戲,場景中央上方會顯示陰影效果的得分值
加入計分板 5/5
39
 選取Assets/Prefabs/Characters/enemy1.prefab
 子物件Sorting Layer = Character
 選取Assets/Prefabs/Characters/enemy2.prefab
 子物件Sorting Layer = Character
隨機生成敵人 1/5
40
 選單命令GameObject> Create Empty建立空物件,命名為
EnemySpawners
 重置Transform
 Position(X,Y,Z) = (0, 15, 0)
 選單命令GameObject> Create Empty Child,在EnemySpawners
建立⼀個空子物件,命名為MidSpawner
 重置Transform
 Position(X,Y,Z) = (0.27, 0, 0)
 在MidSpawner加入EnemySpawner.cs腳本
隨機生成敵人 2/5
41
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemySpawner : MonoBehaviour {
public float spawnTime = 5f; //敵人生成間隔時間
public float spawnDelay = 3f; //延遲時間後才開始生成
public GameObject[] enemies; //敵人預製物件庫
void Start () {
InvokeRepeating("Spawn", spawnDelay, spawnTime);
}
void Spawn () {
int enemyIndex = Random.Range(0, enemies.Length);
Instantiate(enemies[enemyIndex], transform.position, transform.rotation);
}
}
隨機生成敵人 3/5
42
 拖曳Assets/Prefabs/Characters/enemy[1~2].prefab到
EnemySpawner腳本的Enemies資料欄
隨機生成敵人 4/5
43
 複製2份MidSpawner,更名為LeftSpawner及RightSpawner
 重置Transform
 LeftSpawner Position(X,Y,Z) = (-13.8, 0, 0)
 RightSpawner Position(X,Y,Z) = (14.5, 0, 0)
 選取Assets/Prefabs/UI/ui_100points.prefab
 子物件Sorting Layer = UI
 測試遊戲
 碰到敵人會損血,擊斃敵人會得分
 玩家及敵人掉落河裡後,並不會被銷毀
隨機生成敵人 5/5
44
 選單命令GameObject> Create Empty建立空物件,命名Destroyer
 Position(X, Y, Z) = (0.54, -13.5, 0)
 Scale(X, Y, Z) = (1.9, 1, 1)
 加入Box Collider 2D
 勾選Is Trigger
 Size(X, Y) = (23, 1.9)
角色溺水作業 1/4
45
 在Destroyer物件加入Remover.cs程式腳本
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
public class Remover : MonoBehaviour {
public GameObject splash; //水花噴濺特效預製物件
void OnTriggerEnter2D(Collider2D col) {
if (col.gameObject.tag == "Player") { //玩家掉落河裡
GameObject.FindGameObjectWithTag("MainCamera").GetComponent<CameraFollow>()
.enabled = false;
GameObject.FindGameObjectWithTag("HealthBar").GetComponent<FollowPlayer>().
enabled = false;
Instantiate(splash, col.transform.position, transform.rotation);
Destroy (col.gameObject);
StartCoroutine("ReloadGame"); //執行重新載入關卡程序
}
角色溺水作業 2/4
46
else { //其它角色掉落河裡
Instantiate(splash, col.transform.position, transform.rotation);
Destroy (col.gameObject);
}
}
IEnumerator ReloadGame() {
yield return new WaitForSeconds(2); //等待2秒
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex,
LoadSceneMode.Single);
}
}
角色溺水作業 3/4
47
 選取Assets/Prefabs/FX/splash.prefab
 Sorting Layer = Foreground
 拖曳Assets/Prefabs/FX/splash.prefab到Splash欄
 測試遊戲
 敵人掉落河裡會濺出水花並消毀
 玩家落河後會濺出水花並重新開始關卡
角色溺水作業 4/4
48
 選取Assets/Prefabs/Props/bombCrate.prefab
 子物件Sorting Layer = Foreground
 選取Assets/Prefabs/Props/healthCrate.prefab
 子物件Sorting Layer = Foreground
 在Assets/Prefabs/Props/healthCrate.prefab之health子物件加
入HealthPickup.cs程式腳本
製作空投道具箱 1/5
49
using UnityEngine;
using System.Collections;
public class HealthPickup : MonoBehaviour {
public float healthBonus; //補充生命值
public AudioClip collect; //收集道具時之音效
private PickupSpawner pickupSpawner; //PickupSpawner程式腳本參照
private Animator anim; //動畫控制器參照
private bool landed; //道具箱落地旗號
void Awake () {
pickupSpawner = GameObject.Find("pickupManager").GetComponent<PickupSpawner>();
anim = transform.root.GetComponent<Animator>();
}
void OnTriggerEnter2D (Collider2D other) {
if (other.tag == "Player") { //玩家碰到道具箱
PlayerHealth playerHealth = other.GetComponent<PlayerHealth>();
playerHealth.health += healthBonus; //補充玩家生命值
playerHealth.health = Mathf.Clamp(playerHealth.health, 0f, 100f); //上限值100
製作空投道具箱 2/5
50
playerHealth.UpdateHealthBar(); //更新顯示玩家生命條
pickupSpawner.StartCoroutine(pickupSpawner.DeliverPickup()); //啟動下一波空投程序
AudioSource.PlayClipAtPoint(collect,transform.position); //撥放音效
Destroy(transform.root.gameObject); //銷毀道具箱
}
else if(other.tag == "ground" && !landed) { //道具箱落地
anim.SetTrigger("Land"); //觸發道具箱落地動畫
transform.parent = null;
gameObject.AddComponent<Rigidbody2D>();
landed = true;
}
}
}
 拖曳Assets/Audio/FX/healthPickup.ogg到
Collect欄
製作空投道具箱 3/5
51
 在Assets/Prefabs/Props/bombCrate.prefab之crate子物件加入
BombPickup.cs程式腳本
using UnityEngine;
using System.Collections;
public class BombPickup : MonoBehaviour {
public AudioClip pickupClip; //收集道具時之音效
private Animator anim; //動畫控制器參照
private bool landed = false; //道具箱落地旗號
void Awake() {
anim = transform.root.GetComponent<Animator>();
}
void OnTriggerEnter2D (Collider2D other) {
if (other.tag == "Player") { //玩家碰到道具箱
AudioSource.PlayClipAtPoint(pickupClip, transform.position);
other.GetComponent<LayBombs>().bombCount++; //增加玩家炸彈數量
Destroy(transform.root.gameObject); //銷毀道具箱
}
製作空投道具箱 4/5
52
else if (other.tag == "ground" && !landed) { //道具箱落地
anim.SetTrigger("Land"); //觸發道具箱落地動畫
transform.parent = null;
gameObject.AddComponent<Rigidbody2D>();
landed = true;
}
}
}
 拖曳Assets/Audio/Player/Taunts/Player-IDefyYou.wav到
Pickup Clip欄
製作空投道具箱 5/5
53
 選單命令GameObject> Create Empty建立空物件,命名
pickupManager
 重置Transform
 加入PickupSpawner.cs程式腳本
空投道具 1/4
54
using UnityEngine;
using System.Collections;
public class PickupSpawner : MonoBehaviour {
public GameObject[] pickups; //道具預製物件陣列
public float pickupDeliveryTime = 5f; //傳送道具等待時間
public float dropRangeLeft; //道具空投範圍左邊界坐標
public float dropRangeRight; //道具空投範圍右邊界坐標
public float highHealthThreshold = 75f; //玩家生命值超過此設定值時,只空投炸彈道具
public float lowHealthThreshold = 25f; //玩家生命值低於此設定值時,只空投傷藥道具
private PlayerHealth playerHealth; //PlayerHealth程式腳本參照
void Awake () {
playerHealth = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerHea
lth>();
}
空投道具 2/4
55
void Start () {
StartCoroutine(DeliverPickup()); //啟動DeliverPickup程序
}
public IEnumerator DeliverPickup() {
yield return new WaitForSeconds(pickupDeliveryTime); //等待一段指定時間
float dropPosX = Random.Range(dropRangeLeft, dropRangeRight);//隨機空投X坐標
Vector3 dropPos = new Vector3(dropPosX, 15f, 1f); //空投位置
if (playerHealth.health >= highHealthThreshold) //空投炸彈
Instantiate(pickups[0], dropPos, Quaternion.identity);
else if (playerHealth.health <= lowHealthThreshold) //空投傷藥
Instantiate(pickups[1], dropPos, Quaternion.identity);
else { //隨機空投道具
int pickupIndex = Random.Range(0, pickups.Length);
Instantiate(pickups[pickupIndex], dropPos, Quaternion.identity);
}
}
}
空投道具 3/4
56
 設定Pickups Spawner
 拖曳Assets/Prefabs/Props/bombCrate.prefab到Pickups欄
 拖曳Assets/Prefabs/Props/healthCrate.prefab到Pickups欄
 Pickup Delivery Time = 5
 Drop Range Left = -15
 Drop Range Right = 15
 High Health Threshold = 75
 Low Health Threshold = 25
 測試遊戲,會隨機飄下道具
 玩家Player Health之Health值小於25時,⼀定飄下急救箱
 玩家Player Health之Health值大於75時,⼀定飄下炸彈
空投道具 4/4
57
 選單命令GameObject> UI> Raw Image,命名為ui_bombHUD
 Anchor Presets = bottom, left
 Pos(X, Y, Z) = (10, 10, 0)
 Width = 84, Height = 70
 Pivot(X, Y) = (0, 0)
 拖曳Assets/Sprites/_Props/
prop_crate_ammo.png到Texture欄
製作炸彈圖示
58
 將Assets/Prefabs/Props/explosionParticle.prefab加到場景
 選取Assets/Prefabs/Props/bomb.prefab
 Sorting Layer = Character
 在Mr.Bean加入LayBombs.cs程式腳本
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LayBombs : MonoBehaviour {
[HideInInspector]
public bool bombLaid = false; //玩家是否已放置炸彈
public int bombCount = 0; //玩家擁有的炸彈道具個數
public AudioClip bombsAway; //玩家放置炸彈時的語音
public GameObject bomb; //炸彈預製物件
private RawImage bombHUD; //炸彈道具圖示參照,當玩家擁有後就會開啟圖示
玩家放置炸彈 1/3
59
void Awake () {
bombHUD = GameObject.Find("ui_bombHUD").GetComponent<RawImage>();
}
void Update () {
if (Input.GetButtonDown("Fire2") && !bombLaid && bombCount > 0) { //放置炸彈
bombCount--;
bombLaid = true;
AudioSource.PlayClipAtPoint(bombsAway,transform.position);
Instantiate(bomb, transform.position, transform.rotation);
}
bombHUD.enabled = bombCount > 0; //更新炸彈圖示狀態
}
}
玩家放置炸彈 2/3
60
 拖曳Assets/Prefabs/Props/bomb.prefab到Bomb欄
 拖曳Assets/Audio/Player/Taunts/Player-BombsAway.ogg到
Bombs Away欄
 執行遊戲
 Bomb Count大於0時,會顯示炸彈道具圖示
 拿到炸彈道具後,使用滑鼠右鍵放置炸彈
玩家放置炸彈 3/3
61
 選單命令GameObject> Create Empty建立空物件,命名GameManager
 在GameManager加入Pauser.cs程式腳本
using UnityEngine;
using System.Collections;
public class Pauser : MonoBehaviour {
private bool paused = false;
void Update () {
if (Input.GetKeyUp(KeyCode.P)) { //按了P鍵
paused = !paused; //切換暫停狀態
}
if (paused)
Time.timeScale = 0;
else
Time.timeScale = 1;
}
}
 測試遊戲,按P鍵可暫停遊戲
遊戲控制 1/2
62
 編輯GameManager.cs程式腳本,按Esc鍵可結束遊戲
using UnityEngine;
using System.Collections;
public class Pauser : MonoBehaviour {
private bool paused = false;
void Update () {
if (Input.GetKey (KeyCode.Escape)) { //按了Esc鍵
Application.Quit (); //結束遊戲
}
if (Input.GetKeyUp(KeyCode.P)) { //按了P鍵
...
}
}
註:需建立執行檔測試
遊戲控制 2/2
63
 選單命令Files>Build Settings…
 設定遊戲場景、選擇遊戲平台
 點擊Build按鈕
建立執行檔
64

More Related Content

What's hot

A split screen-viable UI event system - Unite Copenhagen 2019
A split screen-viable UI event system - Unite Copenhagen 2019A split screen-viable UI event system - Unite Copenhagen 2019
A split screen-viable UI event system - Unite Copenhagen 2019Unity Technologies
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)noorcon
 
Creating Games for Asha - platform
Creating Games for Asha - platformCreating Games for Asha - platform
Creating Games for Asha - platformJussi Pohjolainen
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)noorcon
 
Fps tutorial 2
Fps tutorial 2Fps tutorial 2
Fps tutorial 2unityshare
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)noorcon
 
Fps tutorial 1
Fps tutorial 1Fps tutorial 1
Fps tutorial 1unityshare
 
Building a turn-based game prototype using ECS - Unite Copenhagen 2019
Building a turn-based game prototype using ECS - Unite Copenhagen 2019Building a turn-based game prototype using ECS - Unite Copenhagen 2019
Building a turn-based game prototype using ECS - Unite Copenhagen 2019Unity Technologies
 
Cross-scene references: A shock to the system - Unite Copenhagen 2019
Cross-scene references: A shock to the system - Unite Copenhagen 2019Cross-scene references: A shock to the system - Unite Copenhagen 2019
Cross-scene references: A shock to the system - Unite Copenhagen 2019Unity Technologies
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)noorcon
 
The Ring programming language version 1.4.1 book - Part 19 of 31
The Ring programming language version 1.4.1 book - Part 19 of 31The Ring programming language version 1.4.1 book - Part 19 of 31
The Ring programming language version 1.4.1 book - Part 19 of 31Mahmoud Samir Fayed
 
building_games_with_ruby_rubyconf
building_games_with_ruby_rubyconfbuilding_games_with_ruby_rubyconf
building_games_with_ruby_rubyconftutorialsruby
 
We Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle Games
We Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle GamesWe Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle Games
We Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle GamesUnity Technologies
 
A Development of Log-based Game AI using Deep Learning
A Development of Log-based Game AI using Deep LearningA Development of Log-based Game AI using Deep Learning
A Development of Log-based Game AI using Deep LearningSuntae Kim
 
libGDX: Simple Frame Animation
libGDX: Simple Frame AnimationlibGDX: Simple Frame Animation
libGDX: Simple Frame AnimationJussi Pohjolainen
 
Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)
 Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version) Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)
Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)Tobias Pfeiffer
 

What's hot (19)

Tdd in unity
Tdd in unityTdd in unity
Tdd in unity
 
A split screen-viable UI event system - Unite Copenhagen 2019
A split screen-viable UI event system - Unite Copenhagen 2019A split screen-viable UI event system - Unite Copenhagen 2019
A split screen-viable UI event system - Unite Copenhagen 2019
 
libGDX: User Input
libGDX: User InputlibGDX: User Input
libGDX: User Input
 
Code Pad
Code PadCode Pad
Code Pad
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 7 (Preview)
 
Creating Games for Asha - platform
Creating Games for Asha - platformCreating Games for Asha - platform
Creating Games for Asha - platform
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 6 (Preview)
 
Fps tutorial 2
Fps tutorial 2Fps tutorial 2
Fps tutorial 2
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 2 (Preview)
 
Fps tutorial 1
Fps tutorial 1Fps tutorial 1
Fps tutorial 1
 
Building a turn-based game prototype using ECS - Unite Copenhagen 2019
Building a turn-based game prototype using ECS - Unite Copenhagen 2019Building a turn-based game prototype using ECS - Unite Copenhagen 2019
Building a turn-based game prototype using ECS - Unite Copenhagen 2019
 
Cross-scene references: A shock to the system - Unite Copenhagen 2019
Cross-scene references: A shock to the system - Unite Copenhagen 2019Cross-scene references: A shock to the system - Unite Copenhagen 2019
Cross-scene references: A shock to the system - Unite Copenhagen 2019
 
Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)
Introduction to Game Programming: Using C# and Unity 3D - Chapter 3 (Preview)
 
The Ring programming language version 1.4.1 book - Part 19 of 31
The Ring programming language version 1.4.1 book - Part 19 of 31The Ring programming language version 1.4.1 book - Part 19 of 31
The Ring programming language version 1.4.1 book - Part 19 of 31
 
building_games_with_ruby_rubyconf
building_games_with_ruby_rubyconfbuilding_games_with_ruby_rubyconf
building_games_with_ruby_rubyconf
 
We Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle Games
We Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle GamesWe Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle Games
We Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle Games
 
A Development of Log-based Game AI using Deep Learning
A Development of Log-based Game AI using Deep LearningA Development of Log-based Game AI using Deep Learning
A Development of Log-based Game AI using Deep Learning
 
libGDX: Simple Frame Animation
libGDX: Simple Frame AnimationlibGDX: Simple Frame Animation
libGDX: Simple Frame Animation
 
Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)
 Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version) Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)
Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)
 

Similar to Unity遊戲程式設計 - 2D Platformer遊戲

Monogame Introduction (ENG)
Monogame Introduction (ENG)Monogame Introduction (ENG)
Monogame Introduction (ENG)Aloïs Deniel
 
i need a taking turn method for a player vs computer battleship game.pdf
i need a taking turn method for a player vs computer battleship game.pdfi need a taking turn method for a player vs computer battleship game.pdf
i need a taking turn method for a player vs computer battleship game.pdfpetercoiffeur18
 
Rapid prototyping with ScriptableObjects
Rapid prototyping with ScriptableObjectsRapid prototyping with ScriptableObjects
Rapid prototyping with ScriptableObjectsGiorgio Pomettini
 
Silverlight as a Gaming Platform
Silverlight as a Gaming PlatformSilverlight as a Gaming Platform
Silverlight as a Gaming Platformgoodfriday
 
Gdc09 Minigames
Gdc09 MinigamesGdc09 Minigames
Gdc09 MinigamesSusan Gold
 
Unity 3D Runtime Animation Generation
Unity 3D Runtime Animation GenerationUnity 3D Runtime Animation Generation
Unity 3D Runtime Animation GenerationDustin Graham
 
QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...
QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...
QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...QAFest
 
ARTDM 170, Week 11: User Interaction
ARTDM 170, Week 11: User InteractionARTDM 170, Week 11: User Interaction
ARTDM 170, Week 11: User InteractionGilbert Guerrero
 
Lightweight Multiplayer HTML5 Games with PubNub
Lightweight Multiplayer HTML5 Games with PubNubLightweight Multiplayer HTML5 Games with PubNub
Lightweight Multiplayer HTML5 Games with PubNubPubNub
 
Report: Avalanche 'very likely' to host outdoor game at Coors Field
Report: Avalanche 'very likely' to host outdoor game at Coors FieldReport: Avalanche 'very likely' to host outdoor game at Coors Field
Report: Avalanche 'very likely' to host outdoor game at Coors Fieldfabulouspsychop39
 
C++ game development with oxygine
C++ game development with oxygineC++ game development with oxygine
C++ game development with oxyginecorehard_by
 
Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017
Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017
Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017Lviv Startup Club
 
20141030 html5j-firefox os-deviceapi
20141030 html5j-firefox os-deviceapi20141030 html5j-firefox os-deviceapi
20141030 html5j-firefox os-deviceapiNoritada Shimizu
 
Oxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcesOxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcescorehard_by
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationIvan Dolgushin
 
Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)fefe7270
 

Similar to Unity遊戲程式設計 - 2D Platformer遊戲 (20)

Flappy bird
Flappy birdFlappy bird
Flappy bird
 
Unity3 d devfest-2014
Unity3 d devfest-2014Unity3 d devfest-2014
Unity3 d devfest-2014
 
Monogame Introduction (ENG)
Monogame Introduction (ENG)Monogame Introduction (ENG)
Monogame Introduction (ENG)
 
i need a taking turn method for a player vs computer battleship game.pdf
i need a taking turn method for a player vs computer battleship game.pdfi need a taking turn method for a player vs computer battleship game.pdf
i need a taking turn method for a player vs computer battleship game.pdf
 
Rapid prototyping with ScriptableObjects
Rapid prototyping with ScriptableObjectsRapid prototyping with ScriptableObjects
Rapid prototyping with ScriptableObjects
 
Silverlight as a Gaming Platform
Silverlight as a Gaming PlatformSilverlight as a Gaming Platform
Silverlight as a Gaming Platform
 
Gdc09 Minigames
Gdc09 MinigamesGdc09 Minigames
Gdc09 Minigames
 
Unity 3D Runtime Animation Generation
Unity 3D Runtime Animation GenerationUnity 3D Runtime Animation Generation
Unity 3D Runtime Animation Generation
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...
QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...
QA Fest 2019. Алексей Альтер-Песоцкий. Snapshot testing with native mobile fr...
 
ARTDM 170, Week 11: User Interaction
ARTDM 170, Week 11: User InteractionARTDM 170, Week 11: User Interaction
ARTDM 170, Week 11: User Interaction
 
Lightweight Multiplayer HTML5 Games with PubNub
Lightweight Multiplayer HTML5 Games with PubNubLightweight Multiplayer HTML5 Games with PubNub
Lightweight Multiplayer HTML5 Games with PubNub
 
Report: Avalanche 'very likely' to host outdoor game at Coors Field
Report: Avalanche 'very likely' to host outdoor game at Coors FieldReport: Avalanche 'very likely' to host outdoor game at Coors Field
Report: Avalanche 'very likely' to host outdoor game at Coors Field
 
C++ game development with oxygine
C++ game development with oxygineC++ game development with oxygine
C++ game development with oxygine
 
Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017
Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017
Анатолій Ландишев - “Незв’язний код у Unity” GameCC 2017
 
20141030 html5j-firefox os-deviceapi
20141030 html5j-firefox os-deviceapi20141030 html5j-firefox os-deviceapi
20141030 html5j-firefox os-deviceapi
 
Oxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcesOxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resources
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code Generation
 
Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)
 
Unity3D Programming
Unity3D ProgrammingUnity3D Programming
Unity3D Programming
 

More from 吳錫修 (ShyiShiou Wu)

Unity遊戲程式設計 - 2D移動與碰撞處理II
Unity遊戲程式設計 - 2D移動與碰撞處理IIUnity遊戲程式設計 - 2D移動與碰撞處理II
Unity遊戲程式設計 - 2D移動與碰撞處理II吳錫修 (ShyiShiou Wu)
 
Unity遊戲程式設計 - 2D運動與碰撞處理I
Unity遊戲程式設計 - 2D運動與碰撞處理IUnity遊戲程式設計 - 2D運動與碰撞處理I
Unity遊戲程式設計 - 2D運動與碰撞處理I吳錫修 (ShyiShiou Wu)
 
Unity遊戲設計- 2D動畫製作及應用
Unity遊戲設計-  2D動畫製作及應用Unity遊戲設計-  2D動畫製作及應用
Unity遊戲設計- 2D動畫製作及應用吳錫修 (ShyiShiou Wu)
 

More from 吳錫修 (ShyiShiou Wu) (20)

Vuforia AR影片程式設計
Vuforia AR影片程式設計Vuforia AR影片程式設計
Vuforia AR影片程式設計
 
micro:bit亮度感測應用
micro:bit亮度感測應用micro:bit亮度感測應用
micro:bit亮度感測應用
 
Vuforia AR 同時追踨多張辨識圖
Vuforia AR同時追踨多張辨識圖Vuforia AR同時追踨多張辨識圖
Vuforia AR 同時追踨多張辨識圖
 
micro:bit開關控制應用
micro:bit開關控制應用micro:bit開關控制應用
micro:bit開關控制應用
 
Vuforia AR 應用程式設計入門
Vuforia AR應用程式設計入門Vuforia AR應用程式設計入門
Vuforia AR 應用程式設計入門
 
Vuforia AR 應用程式準備作業
Vuforia AR應用程式準備作業Vuforia AR應用程式準備作業
Vuforia AR 應用程式準備作業
 
micro:bit LED顯示控制
micro:bit LED顯示控制micro:bit LED顯示控制
micro:bit LED顯示控制
 
IDE for micro:bit
IDE for micro:bitIDE for micro:bit
IDE for micro:bit
 
Microbit 1 introduction
Microbit 1 introductionMicrobit 1 introduction
Microbit 1 introduction
 
Arduino overview
Arduino overviewArduino overview
Arduino overview
 
使用Makeblock App學習mBot程式設計
使用Makeblock App學習mBot程式設計使用Makeblock App學習mBot程式設計
使用Makeblock App學習mBot程式設計
 
使用M部落App學習mBot程式設計
使用M部落App學習mBot程式設計使用M部落App學習mBot程式設計
使用M部落App學習mBot程式設計
 
nodeMCU IOT教學03 - NodeMCU導論
nodeMCU IOT教學03 - NodeMCU導論nodeMCU IOT教學03 - NodeMCU導論
nodeMCU IOT教學03 - NodeMCU導論
 
nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言
 
Unity遊戲程式設計 - 2D移動與碰撞處理II
Unity遊戲程式設計 - 2D移動與碰撞處理IIUnity遊戲程式設計 - 2D移動與碰撞處理II
Unity遊戲程式設計 - 2D移動與碰撞處理II
 
Unity遊戲程式設計 - 2D運動與碰撞處理I
Unity遊戲程式設計 - 2D運動與碰撞處理IUnity遊戲程式設計 - 2D運動與碰撞處理I
Unity遊戲程式設計 - 2D運動與碰撞處理I
 
Python與Ardinio整合應用
Python與Ardinio整合應用Python與Ardinio整合應用
Python與Ardinio整合應用
 
mBlock積木式設計程式
mBlock積木式設計程式mBlock積木式設計程式
mBlock積木式設計程式
 
Arduino程式除錯
Arduino程式除錯Arduino程式除錯
Arduino程式除錯
 
Unity遊戲設計- 2D動畫製作及應用
Unity遊戲設計-  2D動畫製作及應用Unity遊戲設計-  2D動畫製作及應用
Unity遊戲設計- 2D動畫製作及應用
 

Recently uploaded

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile EnvironmentVictorSzoltysek
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 

Recently uploaded (20)

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 

Unity遊戲程式設計 - 2D Platformer遊戲

  • 1. 2D Platformer遊戲 Revised on January 1, 2020  背景動畫與背景音樂  玩家角色控制  隨機生成敵人  空投道具  使用道具  顯示分數  暫停遊戲控制
  • 2.  建立2D專案,my2DPlatformer  選單命令File> Save As…,將預設場景另存新檔  Exercise.unity  調整Main Camera  Position(X, Y, Z) = (-4.43, -0.15, -10)  Background(R, G, B, A) = (163, 187, 196, 5)  Size = 11  Free Aspect  滙入遊戲資源  選單命令Assets> Import Package> Custom Package…,滙入 platformer2d.unitypackage 建立專案 1/3 2
  • 3.  新增Tags  ground、Crate、Enemy、Wall、Obstacle、 Bullet、BombPickup、ExplosionFX、 HealthBar  新增Sorting Layers (遊戲圖層)  Background、Character、Foreground、UI  新增Layers (碰撞管理圖層)  Bombs、Player、Enemies、Pickups、 Ground 建立專案 2/3 3
  • 4.  選單命令Edit> Project Settings…  Physics 2D Layer Collicion Matrix 建立專案 3/3 4
  • 5.  將Assets/Prefebs/Environment/backgrounds.prefab加到場景  Sorting Layer = Background  設定所有子物件Sorting Layer = Background  將Assets/Prefabs/Environment/Foregrounds.prefab加到場景  設定所有子物件Sorting Layer = Foreground 建立場景 5
  • 6.  選取Prefabs/Props/swan.prefab  Sorting Layer = Background  選取Prefabs/Environment/Cab.prefab  Sorting Layer = Background  Wheels子物件  Sorting Layer = Background  選取Prefabs/Environment/Bus.prefab  Sorting Layer = Background  Wheels子物件  Sorting Layer = Background 設定背景動畫預製物件 6
  • 7.  在_Scripts目錄下新增BackgroundPropSpawner.cs程式腳本 using UnityEngine; using System.Collections; public class BackgroundPropSpawner : MonoBehaviour { public Rigidbody2D backgroundProp; //待生成的背景預製物件 public float leftSpawnPosX; //左側生成位置x座標 public float rightSpawnPosX; //右側生成位置x座標 public float minSpawnPosY; //生成位置y座標區間最小值 public float maxSpawnPosY; //生成位置y座標區間最大值 public float minTimeBetweenSpawns; //生成間隔時間最小值 public float maxTimeBetweenSpawns; //生成間隔時間最大值 public float minSpeed; //最小移動速度 public float maxSpeed; //移動速度最大值 void Start () { Random.InitState(System.DateTime.Today.Millisecond); StartCoroutine("Spawn"); //起始Spawn程序 } 隨機產生背景動畫物件 1/6 7
  • 8. IEnumerator Spawn () { float waitTime = Random.Range(minTimeBetweenSpawns, maxTimeBetweenSpawns); yield return new WaitForSeconds(waitTime); //隨機等待一段時間 bool facingLeft = Random.Range(0,2) == 0; //隨機設定預製物件方向 float posX = facingLeft ? rightSpawnPosX : leftSpawnPosX; float posY = Random.Range(minSpawnPosY, maxSpawnPosY); Vector3 spawnPos = new Vector3(posX, posY, transform.position.z); Rigidbody2D propInstance = Instantiate(backgroundProp, spawnPos, Quaternion.identity) as Rigidbody2D; if (!facingLeft) { Vector3 scale = propInstance.transform.localScale; scale.x *= -1; propInstance.transform.localScale = scale; } float speed = Random.Range(minSpeed, maxSpeed); //隨機設定速度 speed *= facingLeft ? -1f : 1f; propInstance.velocity = new Vector2(speed, 0); StartCoroutine(Spawn()); 隨機產生背景動畫物件 2/6 8
  • 9. while (propInstance != null) { if (facingLeft) { if (propInstance.transform.position.x < leftSpawnPosX - 0.5f) Destroy(propInstance.gameObject); } else { if (propInstance.transform.position.x > rightSpawnPosX + 0.5f) Destroy(propInstance.gameObject); } yield return null; } } } 隨機產生背景動畫物件 3/6 9
  • 10.  新增空物件,命名為swanCreator  重置Transform  加入BackgroundPropSpawner.cs程式腳本  拖曳Prefabs/Props/swan.prefab到Prop欄  Left Spawn Pos X = -24  Right Spawn Pos X = 24  Min Spawn Pos Y = 4  Max Spawn Pos Y = 8  Min Time Between Spawns = 2  Max Time Between Spawns = 8  Min Speed = 5  Max Speed = 8  測試遊戲,天空會隨機有天鵝飛過 隨機產生背景動畫物件 4/6 10
  • 11.  新增空物件,命名為busCreator  重置Transform  加入BackgroundPropSpawner.cs程式腳本  拖曳Prefabs/Environment/Bus.prefab到Prop欄  Left Spawn Pos X = -24  Right Spawn Pos X = 24  Min Spawn Pos Y = -5.5  Max Spawn Pos Y = -5.5  Min Time Between Spawns = 8  Max Time Between Spawns = 18  Min Speed = 5  Max Speed = 8  測試遊戲,街道會隨機有巴士通過 隨機產生背景動畫物件 5/6 11
  • 12.  新增空物件,命名為cabCreator  重置Transform  加入BackgroundPropSpawner.cs程式腳本  拖曳Prefabs/Environment/Cab.prefab到Prop欄  Left Spawn Pos X = -24  Right Spawn Pos X = 24  Min Spawn Pos Y = -6.4  Max Spawn Pos Y = -6.4  Min Time Between Spawns = 10  Max Time Between Spawns = 15  Min Speed = 5  Max Speed = 8  測試遊戲,街道會隨機有計程車通過 隨機產生背景動畫物件 6/6 12
  • 13.  新增空物件,命名為music  重置Transform  加入AudioSource元件  AudioClip = MainTheme  勾選Play On Awake  勾選Loop  Volume = 0.1  Reverb Zone Mix = 0  測試專案,遊戲執行時會持續撥放背景音樂 加入背景音樂 13
  • 14.  將Assets/Prefabs/Chractera/Mr.Bean.prefab加倒場景  設定所有子物件Sorting Layer = Character  Tag = Player  Layer = Player 建立玩家角色 14
  • 16.  在Mr.Bean物件加入PlayerControl.cs程式腳本 using UnityEngine; using System.Collections; public class PlayerControl : MonoBehaviour { [HideInInspector] public bool facingRight = true; //方向旗號,不顯示在屬性窗格,但可提其它程式腳本存取 [HideInInspector] public bool jump = false; //跳躍旗號,不顯示在屬性窗格,但可提其它程式腳本存取 public float moveForce = 365f; //行進力道 public float maxSpeed = 5f; //移動速度上限 public AudioClip[] jumpClips; //跳躍動作音效庫 public float jumpForce = 1000f; //跳躍力道 private Transform groundCheck; //用來檢查玩家角色是否站在地面 private bool grounded = false; //落地旗號 private Animator anim; //玩家角色動作控制器參照 玩家角色控制 2/5 16
  • 17. void Awake() { groundCheck = transform.Find("groundCheck"); anim = GetComponent<Animator>(); } void Update() { grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground")); //玩家角色位於在地面,並按下Jump鍵 if (Input.GetButtonDown("Jump") && grounded) jump = true; //執行跳躍動作 } 玩家角色控制 3/5 17
  • 18. void FixedUpdate () { float h = Input.GetAxis("Horizontal"); anim.SetFloat("Speed", Mathf.Abs(h)); if (h * GetComponent<Rigidbody2D>().velocity.x < maxSpeed) GetComponent<Rigidbody2D>().AddForce(Vector2.right * h * moveForce); //加速 if (Mathf.Abs(GetComponent<Rigidbody2D>().velocity.x) > maxSpeed) GetComponent<Rigidbody2D>().velocity = new Vector2(Mathf.Sign(GetComponent<Rigidbody2D>().velocity.x) * maxSpeed, GetComponent<Rigidbody2D>().velocity.y); if (h > 0 && !facingRight) Flip(); //反轉方向 else if (h < 0 && facingRight) Flip(); //反轉方向 if (jump) { anim.SetTrigger("Jump"); int i = Random.Range(0, jumpClips.Length); //隨機撥放跳躍音效 AudioSource.PlayClipAtPoint(jumpClips[i], transform.position); GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, jumpForce)); //跳躍 jump = false; //防止重複跳躍 } } 玩家角色控制 4/5 18
  • 19. void Flip () { facingRight = !facingRight; Vector3 theScale = transform.localScale; theScale.x *= -1; transform.localScale = theScale; } }  拖曳Audio/Player/Jumps/Player- jump[1-3].wav到Jump Clips欄  測試遊戲,可操控主角移動  適度調整移動速度及跳躍力道 玩家角色控制 5/5 19
  • 20.  新增空物件,命名為healthUI  Tag = HealthBar  Position(X, Y, Z) = (0, 100, 0)  在healthUI下新增Sprite物件,命名為HealthBar  Position(X, Y, Z) = (-0.83, 0, 0)  拖曳Assets/Sprites/_UI/Health.png到Sprite Renderer之Sprite欄  拖曳Assets/Materials/Health.mat到Sprite Renderer之Material欄  Sorting Layer = Foreground 建立玩家生命條 1/4 20
  • 21.  在healthUI下新增Sprite物件,命名為HealthOutline  Position(X, Y, Z) = (0, 0, 0)  拖曳Assets/Sprites/_UI/Health-bg.png到Sprite Renderer之 Sprite欄  拖曳Assets/Materials/DefaultPixelSnap.mat到Sprite Renderer 之Material欄  Sorting Layer = Foreground 建立玩家生命條 2/4 21
  • 22.  在healthUI加入FollowPlayer.cs程式腳本 using UnityEngine; using System.Collections; public class FollowPlayer : MonoBehaviour { public Vector3 offset; //顯示位置偏移值 private Transform player; void Awake () { player = GameObject.FindGameObjectWithTag("Player").transform; } void Update () { transform.position = player.position + offset; } } 建立玩家生命條 3/4 22
  • 23.  設定healthUI之FollowPlayer  Offset(X, Y, Z) = (0, 1.2, 0)  測試遊戲,玩家角色上方會顯示生命條並且跟隨移動 建立玩家生命條 4/4 23
  • 24.  在Mr.Bean物件加入PlayerHealth.cs程式腳本 using UnityEngine; using System.Collections; public class PlayerHealth : MonoBehaviour { public float health = 100f; //玩家生命值 public float repeatDamagePeriod = 1f; //玩家連續受傷之時時間隔 public AudioClip[] ouchClips; //玩家受傷音效 public float hurtForce = 100f; //玩家受傷時受到之推力 public float damageAmount = 10f; //每次受傷之損血值 private SpriteRenderer healthBar; //玩家生命條之sprite renderer參照 private float lastHitTime; //前次受傷時間戳記 private Vector3 healthScale; //生命條滿格時之大小 private PlayerControl playerControl; //玩家PlayerControl程式腳本參照 private Animator anim; //玩家動作控制器參照 玩家生命值管理 1/4 24
  • 25. void Awake () { playerControl = GetComponent<PlayerControl>(); //玩家PlayerControl參照 healthBar = GameObject.Find("HealthBar").GetComponent<SpriteRenderer>(); anim = GetComponent<Animator>(); //玩家動作控制器參照 healthScale = healthBar.transform.localScale; //記錄生命條滿格之大小 } void OnCollisionEnter2D (Collision2D col) { if (col.gameObject.tag == "Enemy") { //敵人撞到玩家 if (Time.time > lastHitTime + repeatDamagePeriod) { //已達連續受傷之時間間隔 if (health > 0f) { TakeDamage(col.transform); //使玩家損血 lastHitTime = Time.time; //記錄受傷時間 } else { //玩家死亡,使玩家摔落河裡 Collider2D[] cols = GetComponents<Collider2D>(); foreach (Collider2D c in cols) { //將所有Collider2D調整為觸發器 c.isTrigger = true; } SpriteRenderer[] spr = GetComponentsInChildren<SpriteRenderer>(); 玩家生命值管理 2/4 25
  • 26. foreach(SpriteRenderer s in spr) { //將玩家角色移到UI圖層 s.sortingLayerName = "UI"; } GetComponent<PlayerControl>().enabled = false; //停止PlayerControl程式腳本 GetComponentInChildren<Gun>().enabled = false; //停止Gun程式腳本 anim.SetTrigger("Die"); //觸發Die動畫 } } } } void TakeDamage (Transform enemy) { playerControl.jump = false; //停止跳躍 Vector3 hurtVector = transform.position - enemy.position + Vector3.up * 5f; GetComponent<Rigidbody2D>().AddForce(hurtVector * hurtForce);//向玩家施加衝撞力 health -= damageAmount; //扣減玩家血量 UpdateHealthBar(); //更新顯示生命條 int i = Random.Range (0, ouchClips.Length); //隨機撥放玩家受傷音效 AudioSource.PlayClipAtPoint(ouchClips[i], transform.position); } 玩家生命值管理 3/4 26
  • 27. public void UpdateHealthBar () { //根據玩家的生命值,將生命條的顏色設置為綠色和紅色之間的比例 healthBar.material.color = Color.Lerp(Color.green, Color.red, 1 - health * 0.01f); //根據玩家的生命值,調整生命條的寬度 healthBar.transform.localScale = new Vector3(healthScale.x * health * 0.01f, 1, 1); } }  拖曳Assets/Audio/Player/Ouch/Player-ouch[1-4].wav到Ouch Clips欄 玩家生命值管理 4/4 27
  • 29.  在Main Camera加入CameraFollow.cs程式腳本 using UnityEngine; using System.Collections; public class CameraFollow : MonoBehaviour { public float xMargin = 1f; //攝影機啟動跟隨前允許玩家移動的水平位移 public float yMargin = 1f; //攝影機啟動跟隨前允許玩家移動的垂直位移 public float xSmooth = 8f; //使相機平穩地捕捉目標運動之X軸修正值 public float ySmooth = 8f; //使相機平穩地捕捉目標運動之Y軸修正值 public Vector2 maxXAndY; //攝影機位置X與Y座標最大值 public Vector2 minXAndY; //攝影機位置X與Y座標最小值 private Transform player; //玩家角色transform屬性 void Awake () { player = GameObject.FindGameObjectWithTag("Player").transform; } bool CheckXMargin() { return Mathf.Abs(transform.position.x - player.position.x) > xMargin; } 攝影機跟隨玩家移動 2/4 29
  • 30. bool CheckYMargin() { return Mathf.Abs(transform.position.y - player.position.y) > yMargin; } void FixedUpdate () { TrackPlayer(); } void TrackPlayer () { float targetX = transform.position.x; float targetY = transform.position.y; if (CheckXMargin()) targetX = Mathf.Lerp(transform.position.x, player.position.x, xSmooth * Time.deltaTime); if (CheckYMargin()) targetY = Mathf.Lerp(transform.position.y, player.position.y, ySmooth * Time.deltaTime); targetX = Mathf.Clamp(targetX, minXAndY.x, maxXAndY.x); targetY = Mathf.Clamp(targetY, minXAndY.y, maxXAndY.y); transform.position = new Vector3(targetX, targetY, transform.position.z); } } 攝影機跟隨玩家移動 3/4 30
  • 31.  設定Camera Follow參數  X Margin = 2,Y Margin = 2  X Smooth = 2,Y Smooth = 2  Max(X, Y) = (5, 5)  Min(X, Y) = (-5, -5)  測試遊戲,玩家水平或垂直位移超過2時,攝影機就會自動跟隨 攝影機跟隨玩家移動 4/4 31
  • 32.  選取Assets/Prefabs/Props/rocket.prefab  子物件Sorting Layer = Character  在Mr.Bean的Gun子物件加入Gun.cs腳本 using UnityEngine; using System.Collections; public class Gun : MonoBehaviour { public Rigidbody2D rocket; //rocket預製物件 public float speed = 25f; //rocket速度 private PlayerControl playerCtrl; //PlayerControl程式腳本參照 private Animator anim; //角色動畫控制器參照 void Awake() { anim = transform.root.gameObject.GetComponent<Animator>(); playerCtrl = transform.root.GetComponent<PlayerControl>(); } Mr.Bean射擊控制 1/3 32
  • 33. void Update () { if (Input.GetButtonDown("Fire1")) { //按下發射鍵 anim.SetTrigger("Shoot"); GetComponent<AudioSource>().Play(); if (playerCtrl.facingRight) { //向右發射 Rigidbody2D bulletInstance = Instantiate(rocket, transform.position, Quaternion.Euler(new Vector3(0, 0, 0))) as Rigidbody2D; bulletInstance.velocity = new Vector2(speed, 0); } else { //向左發射 Rigidbody2D bulletInstance = Instantiate(rocket, transform.position, Quaternion.Euler(new Vector3(0, 0, 180f))) as Rigidbody2D; bulletInstance.velocity = new Vector2(-speed, 0); } } } } Mr.Bean射擊控制 2/3 33
  • 34.  拖曳Assets/Prefabs/Props/rocket.prefab到Gun腳本的Rocket 資料欄  選取Assets/Prefabs/Props/rocketExplosion.prefab  Sorting Layer = Foreground  測試遊戲,點擊滑鼠左鍵可發射火箭彈 Mr.Bean射擊控制 3/3 34
  • 35.  選單命令GameObject> UI> Text,命名為Score  Anchor Presets = top, center  Pos(X, Y, Z) = (0, -10, 0)  Width = 500, Height = 100  Pivot(X, Y) = (0.5, 1)  Text = Score  Font = BradBunR  Font Size = 80  Alignment = Center  Color = white 加入計分板 1/5 35
  • 36.  在Score加入Score.cs程式腳本 using UnityEngine; using System.Collections; using UnityEngine.UI; public class Score : MonoBehaviour { public int score = 0; //玩家分數值 void Update () { GetComponent<Text>().text = "Score: " + score; //更新顯示分數 } } 加入計分板 2/5 36
  • 37.  選單命令GameObject> UI> Text,命名為Score-shadow  Anchor Presets = top, center  Pos(X, Y, Z) = (0, -14, 0)  Width = 500, Height = 100  Pivot(X, Y) = (0.5, 1)  Text = Score  Font = BradBunR  Font Size = 80  Alignment = Center  Color = black 加入計分板 3/5 37
  • 38.  在Score-shadow加入ScoreShadow.cs程式腳本 using UnityEngine; using System.Collections; using UnityEngine.UI; public class ScoreShadow : MonoBehaviour { public GameObject guiCopy; // Score物件參照 void Awake () { Vector3 behindPos = transform.position; behindPos = new Vector3(guiCopy.transform.position.x, guiCopy.transform.position.y - 4f, guiCopy.transform.position.z); transform.position = behindPos; } void Update () { GetComponent<Text>().text = guiCopy.GetComponent<Text>().text; //同步更新資料 } } 加入計分板 4/5 38
  • 39.  拖曳Score到Score-shadow之Gui Copy欄  調整Hierarhy窗格中物件順序,使Score位於Score-shadow下方  測試遊戲,場景中央上方會顯示陰影效果的得分值 加入計分板 5/5 39
  • 40.  選取Assets/Prefabs/Characters/enemy1.prefab  子物件Sorting Layer = Character  選取Assets/Prefabs/Characters/enemy2.prefab  子物件Sorting Layer = Character 隨機生成敵人 1/5 40
  • 41.  選單命令GameObject> Create Empty建立空物件,命名為 EnemySpawners  重置Transform  Position(X,Y,Z) = (0, 15, 0)  選單命令GameObject> Create Empty Child,在EnemySpawners 建立⼀個空子物件,命名為MidSpawner  重置Transform  Position(X,Y,Z) = (0.27, 0, 0)  在MidSpawner加入EnemySpawner.cs腳本 隨機生成敵人 2/5 41
  • 42. using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemySpawner : MonoBehaviour { public float spawnTime = 5f; //敵人生成間隔時間 public float spawnDelay = 3f; //延遲時間後才開始生成 public GameObject[] enemies; //敵人預製物件庫 void Start () { InvokeRepeating("Spawn", spawnDelay, spawnTime); } void Spawn () { int enemyIndex = Random.Range(0, enemies.Length); Instantiate(enemies[enemyIndex], transform.position, transform.rotation); } } 隨機生成敵人 3/5 42
  • 44.  複製2份MidSpawner,更名為LeftSpawner及RightSpawner  重置Transform  LeftSpawner Position(X,Y,Z) = (-13.8, 0, 0)  RightSpawner Position(X,Y,Z) = (14.5, 0, 0)  選取Assets/Prefabs/UI/ui_100points.prefab  子物件Sorting Layer = UI  測試遊戲  碰到敵人會損血,擊斃敵人會得分  玩家及敵人掉落河裡後,並不會被銷毀 隨機生成敵人 5/5 44
  • 45.  選單命令GameObject> Create Empty建立空物件,命名Destroyer  Position(X, Y, Z) = (0.54, -13.5, 0)  Scale(X, Y, Z) = (1.9, 1, 1)  加入Box Collider 2D  勾選Is Trigger  Size(X, Y) = (23, 1.9) 角色溺水作業 1/4 45
  • 46.  在Destroyer物件加入Remover.cs程式腳本 using UnityEngine; using UnityEngine.SceneManagement; using System.Collections; public class Remover : MonoBehaviour { public GameObject splash; //水花噴濺特效預製物件 void OnTriggerEnter2D(Collider2D col) { if (col.gameObject.tag == "Player") { //玩家掉落河裡 GameObject.FindGameObjectWithTag("MainCamera").GetComponent<CameraFollow>() .enabled = false; GameObject.FindGameObjectWithTag("HealthBar").GetComponent<FollowPlayer>(). enabled = false; Instantiate(splash, col.transform.position, transform.rotation); Destroy (col.gameObject); StartCoroutine("ReloadGame"); //執行重新載入關卡程序 } 角色溺水作業 2/4 46
  • 47. else { //其它角色掉落河裡 Instantiate(splash, col.transform.position, transform.rotation); Destroy (col.gameObject); } } IEnumerator ReloadGame() { yield return new WaitForSeconds(2); //等待2秒 SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single); } } 角色溺水作業 3/4 47
  • 48.  選取Assets/Prefabs/FX/splash.prefab  Sorting Layer = Foreground  拖曳Assets/Prefabs/FX/splash.prefab到Splash欄  測試遊戲  敵人掉落河裡會濺出水花並消毀  玩家落河後會濺出水花並重新開始關卡 角色溺水作業 4/4 48
  • 49.  選取Assets/Prefabs/Props/bombCrate.prefab  子物件Sorting Layer = Foreground  選取Assets/Prefabs/Props/healthCrate.prefab  子物件Sorting Layer = Foreground  在Assets/Prefabs/Props/healthCrate.prefab之health子物件加 入HealthPickup.cs程式腳本 製作空投道具箱 1/5 49
  • 50. using UnityEngine; using System.Collections; public class HealthPickup : MonoBehaviour { public float healthBonus; //補充生命值 public AudioClip collect; //收集道具時之音效 private PickupSpawner pickupSpawner; //PickupSpawner程式腳本參照 private Animator anim; //動畫控制器參照 private bool landed; //道具箱落地旗號 void Awake () { pickupSpawner = GameObject.Find("pickupManager").GetComponent<PickupSpawner>(); anim = transform.root.GetComponent<Animator>(); } void OnTriggerEnter2D (Collider2D other) { if (other.tag == "Player") { //玩家碰到道具箱 PlayerHealth playerHealth = other.GetComponent<PlayerHealth>(); playerHealth.health += healthBonus; //補充玩家生命值 playerHealth.health = Mathf.Clamp(playerHealth.health, 0f, 100f); //上限值100 製作空投道具箱 2/5 50
  • 51. playerHealth.UpdateHealthBar(); //更新顯示玩家生命條 pickupSpawner.StartCoroutine(pickupSpawner.DeliverPickup()); //啟動下一波空投程序 AudioSource.PlayClipAtPoint(collect,transform.position); //撥放音效 Destroy(transform.root.gameObject); //銷毀道具箱 } else if(other.tag == "ground" && !landed) { //道具箱落地 anim.SetTrigger("Land"); //觸發道具箱落地動畫 transform.parent = null; gameObject.AddComponent<Rigidbody2D>(); landed = true; } } }  拖曳Assets/Audio/FX/healthPickup.ogg到 Collect欄 製作空投道具箱 3/5 51
  • 52.  在Assets/Prefabs/Props/bombCrate.prefab之crate子物件加入 BombPickup.cs程式腳本 using UnityEngine; using System.Collections; public class BombPickup : MonoBehaviour { public AudioClip pickupClip; //收集道具時之音效 private Animator anim; //動畫控制器參照 private bool landed = false; //道具箱落地旗號 void Awake() { anim = transform.root.GetComponent<Animator>(); } void OnTriggerEnter2D (Collider2D other) { if (other.tag == "Player") { //玩家碰到道具箱 AudioSource.PlayClipAtPoint(pickupClip, transform.position); other.GetComponent<LayBombs>().bombCount++; //增加玩家炸彈數量 Destroy(transform.root.gameObject); //銷毀道具箱 } 製作空投道具箱 4/5 52
  • 53. else if (other.tag == "ground" && !landed) { //道具箱落地 anim.SetTrigger("Land"); //觸發道具箱落地動畫 transform.parent = null; gameObject.AddComponent<Rigidbody2D>(); landed = true; } } }  拖曳Assets/Audio/Player/Taunts/Player-IDefyYou.wav到 Pickup Clip欄 製作空投道具箱 5/5 53
  • 54.  選單命令GameObject> Create Empty建立空物件,命名 pickupManager  重置Transform  加入PickupSpawner.cs程式腳本 空投道具 1/4 54
  • 55. using UnityEngine; using System.Collections; public class PickupSpawner : MonoBehaviour { public GameObject[] pickups; //道具預製物件陣列 public float pickupDeliveryTime = 5f; //傳送道具等待時間 public float dropRangeLeft; //道具空投範圍左邊界坐標 public float dropRangeRight; //道具空投範圍右邊界坐標 public float highHealthThreshold = 75f; //玩家生命值超過此設定值時,只空投炸彈道具 public float lowHealthThreshold = 25f; //玩家生命值低於此設定值時,只空投傷藥道具 private PlayerHealth playerHealth; //PlayerHealth程式腳本參照 void Awake () { playerHealth = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerHea lth>(); } 空投道具 2/4 55
  • 56. void Start () { StartCoroutine(DeliverPickup()); //啟動DeliverPickup程序 } public IEnumerator DeliverPickup() { yield return new WaitForSeconds(pickupDeliveryTime); //等待一段指定時間 float dropPosX = Random.Range(dropRangeLeft, dropRangeRight);//隨機空投X坐標 Vector3 dropPos = new Vector3(dropPosX, 15f, 1f); //空投位置 if (playerHealth.health >= highHealthThreshold) //空投炸彈 Instantiate(pickups[0], dropPos, Quaternion.identity); else if (playerHealth.health <= lowHealthThreshold) //空投傷藥 Instantiate(pickups[1], dropPos, Quaternion.identity); else { //隨機空投道具 int pickupIndex = Random.Range(0, pickups.Length); Instantiate(pickups[pickupIndex], dropPos, Quaternion.identity); } } } 空投道具 3/4 56
  • 57.  設定Pickups Spawner  拖曳Assets/Prefabs/Props/bombCrate.prefab到Pickups欄  拖曳Assets/Prefabs/Props/healthCrate.prefab到Pickups欄  Pickup Delivery Time = 5  Drop Range Left = -15  Drop Range Right = 15  High Health Threshold = 75  Low Health Threshold = 25  測試遊戲,會隨機飄下道具  玩家Player Health之Health值小於25時,⼀定飄下急救箱  玩家Player Health之Health值大於75時,⼀定飄下炸彈 空投道具 4/4 57
  • 58.  選單命令GameObject> UI> Raw Image,命名為ui_bombHUD  Anchor Presets = bottom, left  Pos(X, Y, Z) = (10, 10, 0)  Width = 84, Height = 70  Pivot(X, Y) = (0, 0)  拖曳Assets/Sprites/_Props/ prop_crate_ammo.png到Texture欄 製作炸彈圖示 58
  • 59.  將Assets/Prefabs/Props/explosionParticle.prefab加到場景  選取Assets/Prefabs/Props/bomb.prefab  Sorting Layer = Character  在Mr.Bean加入LayBombs.cs程式腳本 using UnityEngine; using System.Collections; using UnityEngine.UI; public class LayBombs : MonoBehaviour { [HideInInspector] public bool bombLaid = false; //玩家是否已放置炸彈 public int bombCount = 0; //玩家擁有的炸彈道具個數 public AudioClip bombsAway; //玩家放置炸彈時的語音 public GameObject bomb; //炸彈預製物件 private RawImage bombHUD; //炸彈道具圖示參照,當玩家擁有後就會開啟圖示 玩家放置炸彈 1/3 59
  • 60. void Awake () { bombHUD = GameObject.Find("ui_bombHUD").GetComponent<RawImage>(); } void Update () { if (Input.GetButtonDown("Fire2") && !bombLaid && bombCount > 0) { //放置炸彈 bombCount--; bombLaid = true; AudioSource.PlayClipAtPoint(bombsAway,transform.position); Instantiate(bomb, transform.position, transform.rotation); } bombHUD.enabled = bombCount > 0; //更新炸彈圖示狀態 } } 玩家放置炸彈 2/3 60
  • 61.  拖曳Assets/Prefabs/Props/bomb.prefab到Bomb欄  拖曳Assets/Audio/Player/Taunts/Player-BombsAway.ogg到 Bombs Away欄  執行遊戲  Bomb Count大於0時,會顯示炸彈道具圖示  拿到炸彈道具後,使用滑鼠右鍵放置炸彈 玩家放置炸彈 3/3 61
  • 62.  選單命令GameObject> Create Empty建立空物件,命名GameManager  在GameManager加入Pauser.cs程式腳本 using UnityEngine; using System.Collections; public class Pauser : MonoBehaviour { private bool paused = false; void Update () { if (Input.GetKeyUp(KeyCode.P)) { //按了P鍵 paused = !paused; //切換暫停狀態 } if (paused) Time.timeScale = 0; else Time.timeScale = 1; } }  測試遊戲,按P鍵可暫停遊戲 遊戲控制 1/2 62
  • 63.  編輯GameManager.cs程式腳本,按Esc鍵可結束遊戲 using UnityEngine; using System.Collections; public class Pauser : MonoBehaviour { private bool paused = false; void Update () { if (Input.GetKey (KeyCode.Escape)) { //按了Esc鍵 Application.Quit (); //結束遊戲 } if (Input.GetKeyUp(KeyCode.P)) { //按了P鍵 ... } } 註:需建立執行檔測試 遊戲控制 2/2 63
  • 64.  選單命令Files>Build Settings…  設定遊戲場景、選擇遊戲平台  點擊Build按鈕 建立執行檔 64