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

Unity:如何在迭代器中获取Random.Range生成的骰子掷骰结果

解决Unity骰子协程结果无法外部获取的问题

你遇到的核心问题是协程是异步执行的,不能直接返回值——当你调用StartCoroutine后,主代码会继续往下走,而协程里的滚动逻辑还在后台执行,所以没法直接拿到finalSide。不过我们可以用回调机制(委托或UnityEvent)来解决这个问题,让骰子滚动完成后主动把结果传递给需要的地方。

接下来我会给出两种常用的解决方案,你可以根据自己的需求选择:


方案1:使用C#委托(Action)传递结果

这种方式适合代码驱动的逻辑,灵活性高。我们在Dice类里定义一个委托事件,当骰子滚动结束时触发它,把最终结果传出去。

修改后的Dice脚本:

using System.Collections;
using System;
using UnityEngine;

public class Dice : MonoBehaviour {
    private Sprite[] diceSides;
    private SpriteRenderer rend;
    // 定义一个回调事件,参数是骰子的最终结果(1-6)
    public Action<int> OnDiceRolled;

    private void Start () {
        rend = GetComponent<SpriteRenderer>();
        diceSides = Resources.LoadAll<Sprite>("DiceSides/");
    }

    private void OnMouseDown() {
        // 防止重复点击,先禁用组件
        this.enabled = false;
        StartCoroutine(RollTheDice());
    }

    private IEnumerator RollTheDice() {
        int randomDiceSide = 0;
        int finalSide = 0;

        // 模拟骰子滚动动画
        for (int i = 0; i <= 20; i++) {
            // 这里注意:Random.Range是左闭右开,所以0到6才会取0-5(对应6个面)
            randomDiceSide = Random.Range(0, 6);
            rend.sprite = diceSides[randomDiceSide];
            yield return new WaitForSeconds(0.05f);
        }

        finalSide = randomDiceSide + 1;
        Debug.Log($"最终掷骰结果:{finalSide}");

        // 触发回调,把结果传递出去(?.是空值保护,防止没有订阅时报错)
        OnDiceRolled?.Invoke(finalSide);

        // 滚动结束后重新启用组件,允许再次点击
        this.enabled = true;
    }
}

在外部脚本中使用(比如GameManager):

你可以在任何需要处理掷骰结果的脚本里订阅这个事件,比如:

using UnityEngine;

public class GameManager : MonoBehaviour {
    // 在Inspector里拖入你的Dice对象
    public Dice dice;

    private void Start() {
        // 订阅骰子滚动完成的事件
        dice.OnDiceRolled += HandleDiceResult;
    }

    // 处理掷骰结果的方法,参数是骰子的最终值
    private void HandleDiceResult(int diceResult) {
        Debug.Log($"收到骰子结果:{diceResult},开始执行后续操作...");
        
        // 这里写你的业务逻辑,比如:
        if (diceResult == 6) {
            GivePlayerExtraTurn();
        } else {
            MovePlayer(diceResult);
        }
    }

    private void GivePlayerExtraTurn() {
        Debug.Log("掷出6点!获得额外回合!");
        // 额外回合的逻辑代码
    }

    private void MovePlayer(int steps) {
        Debug.Log($"移动{steps}步");
        // 移动角色的逻辑代码
    }

    // 记得在销毁时取消订阅,避免内存泄漏
    private void OnDestroy() {
        dice.OnDiceRolled -= HandleDiceResult;
    }
}

方案2:使用UnityEvent(可视化绑定)

如果你更喜欢在Inspector里可视化绑定逻辑,不需要写代码订阅,可以用Unity自带的UnityEvent,它支持在编辑器里拖曳绑定方法。

修改后的Dice脚本:

using System.Collections;
using UnityEngine;
using UnityEngine.Events;

public class Dice : MonoBehaviour {
    private Sprite[] diceSides;
    private SpriteRenderer rend;
    // 定义UnityEvent,参数是int类型的掷骰结果
    public UnityEvent<int> OnDiceRolled;

    private void Start () {
        rend = GetComponent<SpriteRenderer>();
        diceSides = Resources.LoadAll<Sprite>("DiceSides/");
    }

    private void OnMouseDown() {
        this.enabled = false;
        StartCoroutine(RollTheDice());
    }

    private IEnumerator RollTheDice() {
        int randomDiceSide = 0;
        int finalSide = 0;

        for (int i = 0; i <= 20; i++) {
            randomDiceSide = Random.Range(0, 6);
            rend.sprite = diceSides[randomDiceSide];
            yield return new WaitForSeconds(0.05f);
        }

        finalSide = randomDiceSide + 1;
        Debug.Log($"最终掷骰结果:{finalSide}");

        OnDiceRolled?.Invoke(finalSide);
        this.enabled = true;
    }
}

使用方法:

  1. 在Inspector里选中你的Dice对象,找到On Dice Rolled事件。
  2. 点击+号,把需要处理结果的GameObject(比如GameManager)拖到空槽里。
  3. 从下拉菜单中选择对应的方法(比如GameManager的HandleDiceResult,注意方法必须接受一个int参数)。

这样当骰子滚动完成时,就会自动调用你绑定的方法并传递结果。


小提示:

原代码里的Random.Range(0, 5)是错误的——因为Random.Range的第二个参数是排他的,所以0到5只会生成0-4的随机数,对应5个面,而骰子是6面,应该改成Random.Range(0, 6)才能覆盖所有6个面。

内容的提问来源于stack exchange,提问作者M J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 15:08:16