Unity——滾動的小球

工程理解

本游戲為通過鍵盤上的W、A、S、D鍵控制小球的運動軌跡來對固定位置上的小方塊進(jìn)行碰撞,以此來進(jìn)行加分計數(shù)的。
其中主要對象為小球和自轉(zhuǎn)的小方塊;在小球上,我們添加剛體和碰撞盒組件。剛體用于模擬真實的物理運動,碰撞盒子則用于與后面的方塊進(jìn)行碰撞檢測。

效果展示

image-20210425193926982.png
image-20210425220111206.png

核心代碼

一、移動功能

用unity自帶的Input.GetAxis("")函數(shù),Horizontal代表鍵盤的左右鍵(A和D鍵);Vertical代表鍵盤的上下鍵(W和S鍵)。然后用AddForce給予小球一個外力使其按照相應(yīng)的方向動起來。

  //通過鍵盤控制小球移動
    private void FixedUpdate()
    {
        var moveHorizontal = Input.GetAxis("Horizontal"); //水平方向
        var moveVertical = Input.GetAxis("Vertical");//垂直方向
        var movement = new Vector3(moveHorizontal, 0, moveVertical);
        //Vector3三維向量
        m_Rigidbody.AddForce(movement * Speed);
        //Speed 為速度 通過movement和Speed來控制小球的方向和速度
    }

二、計數(shù)功能

  1. 定義了一個m_Count變量來計數(shù)小球碰到方塊的個數(shù);

  2. 并通過GameObject.Destroy(other.gameObject);語句,來對已經(jīng)計數(shù)的方塊進(jìn)行銷毀處理;(我們給方塊修改標(biāo)簽”Tag”,如果小球碰撞的物體標(biāo)簽是方塊的標(biāo)簽名,我們則銷毀此方塊并讓分?jǐn)?shù)加一)

  3. 調(diào)用 SetCountText();函數(shù),將計數(shù)傳給UI進(jìn)行顯示。

//計數(shù)功能
private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Pick Up"))
        {
            GameObject.Destroy(other.gameObject);//銷毀已記數(shù)方塊
            m_Count++;//計數(shù)
            SetCountText();//調(diào)用函數(shù),將個數(shù)傳給UI進(jìn)行顯示
        }
    }

三、UI顯示功能

  1. 將計數(shù)功能所記的數(shù)目傳遞過來,通過 CountText.text = m_Count.ToString();//計數(shù)UI顯示語句,將所計數(shù)目通過UI顯示,其中CountText.text為UI計數(shù)的變量。

  2. 當(dāng)所有小方塊都被碰撞到時,即m_Count >= 8(我這里給的小方塊個數(shù)為8個),輸出游戲成功信息,并儲存在WinText.text中。

private void SetCountText()
    {
        CountText.text = m_Count.ToString();//計數(shù)UI顯示

        if (m_Count >= 8)
        {
            WinText.text = "You Win!";//成功提示
        }
    }
image-20210425194022899.png
image-20210425194052979.png
image-20210425194125286.png

改進(jìn)——框架

由于,假設(shè)將小方塊個數(shù)改為10個,則:

  1. 顯示得分的UI是寫在一起的,當(dāng)修改相對應(yīng)的限制條件時,會受到牽連

  2. 判定輸贏的邏輯也會受到牽連

  3. 顯示輸贏結(jié)算UI邏輯也在一起,也會受到牽連

所以利用框架進(jìn)行改進(jìn)

在框架中,

  • Player:負(fù)責(zé)接收玩家輸入并響應(yīng)角色移動;當(dāng)碰撞到小方塊時,通知Game Mode

  • Game Mode:對全局的游戲規(guī)則、玩法、計分等內(nèi)容進(jìn)行處理;在Player控制器通知Game Mode碰撞到小方塊后,Game Mode進(jìn)行對應(yīng)的計分和輸贏判斷等操作

  • 小方塊:在游戲啟動時把自己的存在告知Game Mode;這樣一來,Game Mode就完全直到當(dāng)前場上有多少個小方塊,就可以動態(tài)的根據(jù)場上方塊數(shù)量來判斷輸贏,而不會在代碼中寫死邏輯了。

相關(guān)代碼:

PickupComponent:

public class PickupComponent : MonoBehaviour
{
    // Start is called before the first frame update
    private void Start()
    {
        //把自己注冊到GameMode
        GameMode.Instance.RegisterPickUp(this);
    }
}

PlayerController控制器:

public class PlayerController : MonoBehaviour
{
    public float Speed;
    
    private Rigidbody m_Rigidbody;
    
    private void Start()
    {
        m_Rigidbody = this.GetComponent<Rigidbody>();
    }

    private void FixedUpdate()
    {
        var moveHorizontal = Input.GetAxis("Horizontal");
        var moveVertical = Input.GetAxis("Vertical");

        var movement = new Vector3(moveHorizontal, 0, moveVertical);
        
        m_Rigidbody.AddForce(movement * Speed);
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Pick Up"))
        {
            var pickupComponent = other.gameObject.GetComponent<PickupComponent>(); 
            if (pickupComponent == null)
            {
                Debug.LogError("有一個Tag是Pickup的GameObject,卻沒有掛載Pickup相關(guān)組件");
            }
            GameMode.Instance.PlayerEnterPickup(pickupComponent);
        }
    }

    
}

GameMode,統(tǒng)一管理游戲的玩法、得分判定、輸贏結(jié)果等內(nèi)容的類:

public class GameMode : MonoBehaviour
{ 
    public static GameMode Instance { get; private set; }
    [Header("計分Text")]
    public Text CountText;

    [Header("顯示W(wǎng)in的文本")]
    public Text WinText;

    private readonly List<PickupComponent> m_Pickups = new List<PickupComponent>();

    private int _count;
    private int m_Count
    {
        get => _count;
        set
        {
            _count = value;
            if (CountText != null)
            {
                CountText.text = value.ToString();
            }
        }
    }
    
    private void Awake()
    {
        if (Instance == null)
            Instance = this;
    }
    public void RegisterPickUp(PickupComponent pickup)
    {
        m_Pickups.Add(pickup);
    }
    public void PlayerEnterPickup(PickupComponent pickup)
    {
        m_Pickups.Remove(pickup);
        GameObject.Destroy(pickup.gameObject);
        m_Count++;
        if (m_Pickups.Count <= 0)
        {
            WinText.text = "You Win!";
        }
    }

    private void Start()
    {
        WinText.text = string.Empty;
        m_Count = 0;
    }

    private void Update()
    {
        if (m_Pickups.Count > 0)
        {
            var rotateValue = new Vector3(15, 30, 45) * Time.deltaTime;
            foreach (var pickup in m_Pickups)
            {
                pickup.transform.Rotate(rotateValue);
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容