簡體   English   中英

Unity 按鈕滾動 3D 骰子,在按鈕上尋找剛體而不是骰子對象

[英]Unity Button to roll 3D dice looking for Rigidbody on the button instead of the die object

我是 Unity 的新手,一直在嘗試擲骰子。 我遇到了一組教程,它們允許我創建一個 3d 模具(模具使用 Rigidbody 和 Mesh Collider)並編寫腳本使其在空格鍵上滾動,如下所示:

骰子.cs:

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

public class Dice : MonoBehaviour
{
    Rigidbody rb;

    bool hasLanded;
    bool thrown;

    Vector3 initPosition;
    
    public int diceValue;

    public DiceSide[] diceSides;


    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        initPosition = transform.position;
        rb.useGravity = false;
    }

    // Update is called once per frame
    void Update()
    {
         if (Input.GetKeyDown(KeyCode.Space)){
            RollDice();
        }

        if (rb.IsSleeping() && !hasLanded && thrown)
        {
            hasLanded = true;
            rb.useGravity = false;
            rb.isKinematic = true;

            SideValueCheck();
        }
        else if (rb.IsSleeping() && hasLanded && diceValue == 0)
        {
            RollAgain();
        }
    }

    void RollDice()
    {
        if (!thrown && !hasLanded)
        {
            thrown = true;
            rb.useGravity = true;
            rb.AddTorque(Random.Range(0, 500), Random.Range(0,500), Random.Range(0, 500));
        }
        else if (thrown && hasLanded)
        {
            Reset();
        }
    }

    void Reset()
    {
        transform.position = initPosition;
        thrown = false;
        hasLanded = false;
        rb.useGravity = false;
        rb.isKinematic = false;
    }

    void RollAgain()
    {
        Reset();
        thrown = true;
        rb.useGravity = true;
        rb.AddTorque(Random.Range(0, 500), Random.Range(0, 500), Random.Range(0, 500));
    }

    void SideValueCheck()
    {
        diceValue = 0;
        foreach (DiceSide side in diceSides)
        {
            if (side.OnGround())
            {
                diceValue = side.sideValue;
                Debug.Log(diceValue + " has been rolled!");
            }
        }
    }
}

DiceSide.cs:

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

public class DiceSide : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

    bool onGround;
    public int sideValue;

    private void OnTriggerStay(Collider col)
    {
        if(col.tag == "Ground")
        {
            onGround = true;
        }
    }

    private void OnTriggerExit(Collider col)
    {
        if(col.tag == "Ground")
        {
            onGround = true;
        }
    }

    public bool OnGround()
    {
        return onGround;
    }
}

骰子的每一面都有一個球體,DiceSide.cs 附加到該球體上,其中包含與給定面相反的邊值,而 Dice.cs 附加到主骰子本身。

以上所有工作都很好。

我面臨的問題是將其調整為我想在單擊按鈕后擲骰子而不是按一個鍵(在本例中為空格鍵)。

為此,我修改了 Dice.cs 代碼如下:

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

public class Dice : MonoBehaviour
{
    Rigidbody rb;

    bool hasLanded;
    bool thrown;

    Vector3 initPosition;

    public int diceValue;

    public DiceSide[] diceSides;


    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        initPosition = transform.position;
        rb.useGravity = false;
    }

    // Update is called once per frame
    void Update()
    {
        if (rb.IsSleeping() && !hasLanded && thrown)
        {
            hasLanded = true;
            rb.useGravity = false;
            rb.isKinematic = true;

            SideValueCheck();
        }
        else if (rb.IsSleeping() && hasLanded && diceValue == 0)
        {
            RollAgain();
        }
    }

    public void RollDice()
    {
        if (!thrown && !hasLanded)
        {
            thrown = true;
            rb.useGravity = true;
            rb.AddTorque(Random.Range(0, 500), Random.Range(0,500), Random.Range(0, 500));
        }
        else if (thrown && hasLanded)
        {
            Reset();
        }
    }

    void Reset()
    {
        transform.position = initPosition;
        thrown = false;
        hasLanded = false;
        rb.useGravity = false;
        rb.isKinematic = false;
    }

    void RollAgain()
    {
        Reset();
        thrown = true;
        rb.useGravity = true;
        rb.AddTorque(Random.Range(0, 500), Random.Range(0, 500), Random.Range(0, 500));
    }

    void SideValueCheck()
    {
        diceValue = 0;
        foreach (DiceSide side in diceSides)
        {
            if (side.OnGround())
            {
                diceValue = side.sideValue;
                Debug.Log(diceValue + " has been rolled!");
            }
        }
    }
}

但是當我將 Dice.cs 腳本拖到按鈕上時,如下所示: 在此處輸入圖片說明

我收到來自 Unity 的錯誤消息說

MissingComponentException:“Button-RollDice”游戲對象沒有附加“Rigidbody”,但腳本正在嘗試訪問它。 您可能需要向游戲對象“Button-RollDice”添加一個剛體。 或者您的腳本需要在使用組件之前檢查它是否已附加。 Dice.Update ()(在 Assets/Dice.cs:35)

我足夠了解代碼正在尋找按鈕上的 Rigidbody 而不是模具,但我不知道如何修改我的代碼以使其按預期在模具上起作用。

謝謝你。

骰子腳本仍然需要在 Dice 對象上。 您需要一個帶有 OnClick 事件的中間腳本來分配給按鈕,並引用 Dice 腳本,然后該腳本可以調用 RollDice。

就像是:


    public class ButtonHandler : MonoBehavior
    {
        // Assign dice game object to script in editor
        public GameObject DiceGameObject;
        private Dice dice;
    
        void Awake()
        {
            // Retrieve the script from the gameobject 
            dice = diceGameObject.GetComponent<Dice>();
        }
    
        public void RollDiceOnClick()
        {
            // Call the roll dice method
            dice.RollDice();
        }
    }

您可以將 RollDiceOnClick() 方法分配給按鈕的 OnClick 事件(而不是 RollDice)。

然后你將骰子游戲對象拖到 DiceGameObject 屬性上,一切都應該鏈接起來

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM