Unity Button 滚动 3D 骰子寻找按钮上的 Rigidbody 而不是骰子对象

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

我是 Unity 的新手,一直在尝试掷骰子。我遇到了一组教程,这些教程允许我创建一个 3d 模具(该模具使用 Rigidbody 和 Mesh Collider)并将其编写为在按下空格键时滚动的脚本,如下所示:

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 (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: There is no 'Rigidbody' attached to the "Button-RollDice" game object, but a script is trying to access it. You probably need to add a Rigidbody to the game object "Button-RollDice". Or your script needs to check if the component is attached before using it. Dice.Update () (at Assets/Dice.cs:35)

我知道代码正在寻找按钮上的刚体而不是骰子,但我不知道如何修改我的代码以使其按预期作用于骰子。

谢谢。

骰子脚本仍需要位于 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 属性 上,一切都应该 link 向上