【问题标题】:Unity Button to roll 3D dice looking for Rigidbody on the button instead of the die objectUnity Button 滚动 3D 骰子在按钮上寻找刚体而不是骰子对象
【发布时间】:2021-08-01 01:59:58
【问题描述】:

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

骰子.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)

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

谢谢。

【问题讨论】:

  • 请删除空的Update/Start/Awake/OrAnyMessageMethods,因为它们会降低性能。
  • 不要将骰子附加到按钮上,而让它附加到之前分配给的游戏对象(对于您说它正在工作的情况)。休息应该像你一样工作:-) 此外,似乎rb 在被分配之前就被调用了。要么禁用 Dice 脚本,直到你按下按钮掷骰子,要么在 Update 方法中添加 if ( rb != null ) 检查以继续,否则立即返回。

标签: c# unity3d rigid-bodies


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2014-03-16
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 2018-09-08
    • 2021-12-25
    相关资源
    最近更新 更多