【发布时间】: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!");
}
}
}
}
我收到 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