❤❤Fungus新課程即將發布,快寫問卷拿優惠❤❤

2017年7月4日 星期二

Unity 打磚塊 2D 教學(下) 過關機制


下載完整可執行遊戲的專案 二合一(台幣約60元)

Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{

    [Header("水平移動速度")]
    public float speedX;
    Rigidbody2D playerRigidbody2D;

    void Start()
    {
        playerRigidbody2D = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        moveLeftOrRight();
    }

    float LeftOrRight()
    {
        return Input.GetAxis("Horizontal");
    }

    void moveLeftOrRight()
    {
        playerRigidbody2D.velocity = LeftOrRight() * new Vector2(speedX, 0);
    }
}
Ball.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Ball : MonoBehaviour
{
    public Text scoreText;
    int score;

    Rigidbody2D ballRigidbody2D;
    CircleCollider2D ballCircleCollider2D;

    [Header("水平速度")]
    public float speedX;

    [Header("垂直速度")]
    public float speedY;

    #region 教學理解用 可不寫
    [Header("實際水平速度")]
    public float velocityX;

    [Header("實際垂直速度")]
    public float velocityY;
    #endregion



    void Start()
    {
        ballRigidbody2D = GetComponent<Rigidbody2D>();
        ballCircleCollider2D = GetComponent<CircleCollider2D>();

        //切換成Kinematic模式
        //Uity 2018版以後不加這行的話 發球之前球會無法跟著球拍移動
        ballRigidbody2D.bodyType = RigidbodyType2D.Kinematic;

        scoreText.text = "目前分數:";
        Invoke("ballStart", 3);
    }

    void Update()
    {
        #region 教學理解用 可不寫
        velocityX = ballRigidbody2D.velocity.x;
        velocityY = ballRigidbody2D.velocity.y;
        #endregion

        if (Input.GetKey(KeyCode.Space))
        {
            ballStart();
        }
    }

    void ballStart()
    {
        if (isStop())
        {
            ballCircleCollider2D.enabled = true;
            transform.SetParent(null);
            ballRigidbody2D.velocity = new Vector2(speedX, speedY);
            
            //Unity 2018以後的版本需要加下面這行:
            //改回預設的Dynamic,使用Unity內建的物理運動規則
            ballRigidbody2D.bodyType = RigidbodyType2D.Dynamic;
        }
    }

    bool isStop()
    {
        return ballRigidbody2D.velocity == Vector2.zero;
    }

    void OnCollisionEnter2D(Collision2D other)
    {
        lockSpeed();
        if (other.gameObject.CompareTag(tags.磚塊.ToString()))
        {
            GameManager.brickCount--;
            Debug.Log("目前磚塊數量: "+GameManager.brickCount);
            GameManager.checLevelClearOrNot();
            other.gameObject.SetActive(false);
            score += 10;
            scoreText.text = "目前分數:" + score;
        }
    }

    void lockSpeed()
    {
        Vector2 lockSpeed = new Vector2(resetSpeedX(), resetSpeedY());
        ballRigidbody2D.velocity = lockSpeed;
    }

    float resetSpeedX()
    {
        float currentSpeedX = ballRigidbody2D.velocity.x;
        if (currentSpeedX < 0)
        {
            return -speedX;
        }
        else
        {
            return speedX;
        }
    }

    float resetSpeedY()
    {
        float currentSpeedY = ballRigidbody2D.velocity.y;
        if (currentSpeedY < 0)
        {
            return -speedY;
        }
        else
        {
            return speedY;
        }
    }
}
Trap.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Trap : MonoBehaviour {
    [Header("被撞到時候的位移")]
    public Vector3 offset;

    public int life;

    private void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.CompareTag(tags.球.ToString()))
        {
            life--;
            gameObject.transform.position += offset;
        }
        if (life<=0&&!GameManager.LevelClear)
        {
            GameManager.ReloadThisScene();
        }

    }

}
GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    [Header("可打破的磚塊初始數量")]
    public static int brickCount;

    static GameObject nextLevelButton;

    public static void ReloadThisScene() {
        Scene current = SceneManager.GetActiveScene();
        SceneManager.LoadScene(current.name);
    }

    public static bool LevelClear {
        get {

            if (brickCount<=0)
            {
                return true;
            }
            return false;
        }
    }
    public static void checLevelClearOrNot() {
        if (LevelClear)
        {
            showNextLevelButton();
        }
    }
    public void GotoScene(string next) {
        SceneManager.LoadScene(next);
    }


    void Start()
    {
        nextLevelButton = GameObject.FindGameObjectWithTag(tags.下一關按鈕.ToString());
        nextLevelButton.SetActive(false);

        brickCount = GameObject.FindGameObjectsWithTag(tags.磚塊.ToString()).Length;
        Debug.Log("一開始有 "+brickCount+" 個可打破的磚塊");
    }

    static void showNextLevelButton() {
        nextLevelButton.SetActive(true);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

enum tags
{
    磚塊, 背景, 球拍, 球, 下一關按鈕
}
上集的程式碼與教學
http://www.morningfungame.com/2017/01/Unity-Arkanoid-breakout-tutorial-2D.html

7 則留言:

  1. 從巴哈一路找到這邊來,發現這邊有非常海量的教學,真的很感謝站長的熱心跟資源分享!!

    回覆刪除
  2. 作者已經移除這則留言。

    回覆刪除
    回覆
    1. unity視窗的左上方有一排按鈕,其中一個可以縮放圖片,你試試看吧

      刪除
  3. 請問一下為什麼你的腳色圖片用在fungus裡的character可以佔整個畫面,我圖片檔案本身也很大但是還是小小一個而已

    回覆刪除
  4. 喔喔,原來你是問fungus喔,他會自動調整角色圖片大小,參考一下這個清單裡的漫畫對話框教學,裡面有提到怎麼改大小
    Unity x Fungus 單篇教學:http://www.youtube.com/playlist?list=PLYGd-m5DMaRaVQ8uJgbXHiPHWF_kdigCN

    回覆刪除
  5. 雖然弄了很久才搞懂一點,不過還是謝謝你

    回覆刪除

留言給作者加油打氣