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

如何在Unity中实现无重复的随机名称生成器

实现Unity中无重复随机名称的两种方案

你的代码目前每次直接从原列表随机选取,自然容易出现重复。这里有两种实用的解决思路,你可以根据自己的需求来选择:

方案1:维护可用名称列表(用完即移除)

这个方法会创建原名称列表的副本,每次随机选出一个名称后就从副本中移除,直到副本为空后可以选择重置。适合需要把所有名称轮一遍再重复的场景。

修改后的代码:

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

public class Names : MonoBehaviour {
    public List<string> names = new List<string>();
    public TMP_Text text;
    // 维护当前可用的名称列表
    private List<string> availableNames;

    private void Start() {
        // 初始化可用列表,复制原列表的所有元素
        availableNames = new List<string>(names);
        DisplayRandomName();
    }

    // 单独抽离显示逻辑,方便后续重复调用(比如按钮触发)
    public void DisplayRandomName() {
        if (availableNames.Count == 0) {
            // 可选逻辑:当所有名称用完后重置可用列表
            availableNames = new List<string>(names);
            Debug.Log("所有名称已用完,重置列表");
        }
        string wordToDisplay = GetUniqueRandomName();
        text.text = wordToDisplay;
    }

    private string GetUniqueRandomName() {
        // 从可用列表中随机选一个索引
        int randomIndex = Random.Range(0, availableNames.Count);
        string selectedName = availableNames[randomIndex];
        // 移除已选中的名称,避免重复
        availableNames.RemoveAt(randomIndex);
        return selectedName;
    }
}

核心说明:

  • 新增availableNames作为临时可用列表,启动时复制原列表内容,和原列表解耦
  • 每次选完名称后立刻从可用列表移除,确保不会再次被选中
  • 可用列表为空时可以手动重置,实现循环复用

方案2:Fisher-Yates洗牌后顺序取用

如果你希望一次性打乱所有名称的顺序,再按顺序逐个取用(避免每次随机的性能开销),可以用经典的Fisher-Yates洗牌算法,配合索引记录当前取用位置。

修改后的代码:

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

public class Names : MonoBehaviour {
    public List<string> names = new List<string>();
    public TMP_Text text;
    // 存储打乱后的名称列表
    private List<string> shuffledNames;
    // 当前取用的索引位置
    private int currentIndex = 0;

    private void Start() {
        ShuffleNames();
        DisplayNextName();
    }

    // Fisher-Yates洗牌算法:高效公平的列表打乱方式
    private void ShuffleNames() {
        shuffledNames = new List<string>(names);
        int n = shuffledNames.Count;
        while (n > 1) {
            n--;
            int k = Random.Range(0, n + 1);
            // 交换两个位置的元素
            string temp = shuffledNames[k];
            shuffledNames[k] = shuffledNames[n];
            shuffledNames[n] = temp;
        }
        currentIndex = 0;
    }

    // 显示下一个名称
    public void DisplayNextName() {
        if (currentIndex >= shuffledNames.Count) {
            // 所有名称用完后重新洗牌
            ShuffleNames();
            Debug.Log("所有名称已用完,重新洗牌");
        }
        text.text = shuffledNames[currentIndex];
        currentIndex++;
    }
}

核心说明:

  • ShuffleNames方法用Fisher-Yates算法打乱列表,比多次随机选取更高效,尤其适合大列表
  • currentIndex记录当前取到第几个元素,每次调用DisplayNextName就取下一个,到末尾后自动重新洗牌

选择建议:

  • 如果需要随机跳着选但不重复,优先选方案1
  • 如果需要按打乱后的固定顺序逐个取用,选方案2,性能表现更好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 11:37:32