You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何正确计算骰子停止滚动后的总点数?

问题修复:骰子点数计算错误与旧值累加问题

问题根源

  1. 重置时机不当:仅在脚本启用时重置计算状态,未在每次掷骰开始时执行重置,导致旧结果残留累加。
  2. 静止判定不准确:依赖 Rigidbody.IsSleeping() 判断骰子是否停止,刚体停止后需延迟才会进入睡眠状态,可能提前触发"全部停止"判定,清空结果列表后丢失后续骰子的点数。
  3. 结果列表过早清空:在显示结果后立即清空列表,若有延迟触发的骰子停止事件,会导致已记录的点数丢失。

修复方案与代码修改

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System.Linq;

public class DisplayCurrentDiceValue : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI _valueText;
    private int totalDiceValue = 0;
    private bool isValueDisplayed = false;
    private List<int> diceResults = new List<int>();

    private void OnEnable()
    {
        DiceManager.OnStopRolling += AddDiceValue;

        if (_valueText == null)
        {
            _valueText = GetComponentInChildren<TextMeshProUGUI>();
        }
        // 初始重置
        ResetRollState();
    }

    private void OnDisable()
    {
        DiceManager.OnStopRolling -= AddDiceValue;
    }

    // 公开重置方法,在每次掷骰开始时调用(比如由DiceManager触发)
    public void ResetRollState()
    {
        totalDiceValue = 0;
        diceResults.Clear();
        isValueDisplayed = false;
        // 清空显示文本
        if (_valueText != null)
        {
            _valueText.text = "0";
        }
    }

    private void AddDiceValue(int faceValue)
    {
        // 仅在未显示结果时添加点数(避免重复添加)
        if (!isValueDisplayed)
        {
            diceResults.Add(faceValue);
            totalDiceValue = diceResults.Sum();
        }

        // 检查所有骰子是否真的静止
        if (IsAllDiceStopped() && !isValueDisplayed)
        {
            UpdateValueText();
            StartCoroutine(BounceInAnimation());
            isValueDisplayed = true;
        }
    }

    private bool IsAllDiceStopped()
    {
        GameObject[] diceObjects = GameObject.FindGameObjectsWithTag("Dice");
        foreach (GameObject diceObject in diceObjects)
        {
            Rigidbody diceRigidbody = diceObject.GetComponent<Rigidbody>();
            if (diceRigidbody == null) continue;

            // 用速度和角速度判断是否静止,比IsSleeping更精准及时
            bool isMoving = diceRigidbody.velocity.magnitude > 0.01f || diceRigidbody.angularVelocity.magnitude > 0.01f;
            if (isMoving)
            {
                return false;
            }
        }
        return true;
    }

    private void UpdateValueText()
    {
        _valueText.text = totalDiceValue.ToString();
    }

    private IEnumerator BounceInAnimation()
    {
        // 保留你的动画逻辑
        yield return null;
    }
}

关键修改说明

  • 新增 ResetRollState 方法:在每次掷骰开始时调用该方法,确保所有计算状态(总和、结果列表、显示标记)完全重置,彻底解决旧值累加问题。
  • 替换静止判定逻辑:改用刚体的线速度和角速度判断是否静止,避免因睡眠延迟导致的误判。
  • 调整结果列表清空时机:仅在重置时清空列表,不再在显示结果后立即清空,确保所有骰子的点数都能被正确记录。
  • 添加状态保护:在 AddDiceValue 中增加 !isValueDisplayed 判断,防止重复添加点数。

使用注意

确保在DiceManager的掷骰开始逻辑中,调用 DisplayCurrentDiceValue.ResetRollState() 方法,比如在玩家点击掷骰按钮时触发重置。

内容的提问来源于stack exchange,提问作者Oueza euloge stephane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 15:45:41