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

Unity库函数GetUniqueInt生成唯一整数数组时崩溃求助

问题原因与解决方案

咱们先拆解导致Unity卡死甚至内存溢出的核心问题,再给出落地的修复方案:

一、核心崩溃原因

结合你提供的代码片段和调用场景GetUniqueInt(5,5)来看,无限循环是导致卡死和内存溢出的罪魁祸首,大概率是以下两种情况之一:

1. 拼写错误引发的逻辑异常

你的代码片段里写了int[] temp = new int[intLengt...——这里明显少了字母h,正确应该是intLength。如果这个拼写错误没修正,要么编译报错,要么运行时会因为数组长度异常,导致重复检查逻辑完全失效,直接陷入无限循环。

2. 逻辑缺陷:无法终止的循环

如果GetUniqueInt的设计逻辑是「从0到intLength-1的范围内,生成intCount个不重复整数」,那会出现两种致命问题:

  • 当intCount > intLength时,根本不可能凑出足够多的唯一值,循环会永远跑下去,持续占用CPU和内存直到溢出;
  • 哪怕是(5,5)这种合法参数,如果随机数范围写错(比如写成Random.Range(0, intLength+1)),也可能出现某个值永远无法被选中,导致循环无法终止。

二、修复方案

推荐两种高效且安全的实现方式,彻底避免无限循环问题:

方案1:洗牌法(适合intCount接近intLength的场景)

先创建包含所有可能值的数组,用Fisher-Yates算法打乱顺序,再取前intCount个值,完全跳过重复检查环节,效率拉满:

using UnityEngine;

namespace MajorSolution
{
    public static class MajorMath
    {
        public static int[] GetUniqueInt(int intCount, int intLength)
        {
            // 先做参数校验,从根源避免无效调用
            if (intCount <= 0 || intLength <= 0 || intCount > intLength)
            {
                Debug.LogError($"无效参数:intCount({intCount})不能大于intLength({intLength}),且两者必须大于0");
                return new int[0];
            }

            // 生成包含0到intLength-1的完整数组
            int[] allValues = new int[intLength];
            for (int i = 0; i < intLength; i++)
            {
                allValues[i] = i;
            }

            // Fisher-Yates洗牌算法打乱数组
            for (int i = intLength - 1; i > 0; i--)
            {
                int randomIndex = Random.Range(0, i + 1);
                // 交换元素
                (allValues[i], allValues[randomIndex]) = (allValues[randomIndex], allValues[i]);
            }

            // 截取前intCount个元素作为结果
            int[] returnValue = new int[intCount];
            System.Array.Copy(allValues, returnValue, intCount);

            return returnValue;
        }
    }
}

方案2:HashSet检查法(适合intCount远小于intLength的场景)

用HashSet快速判断值是否重复,同时增加循环次数上限,彻底杜绝无限循环:

using UnityEngine;
using System.Collections.Generic;

namespace MajorSolution
{
    public static class MajorMath
    {
        public static int[] GetUniqueInt(int intCount, int intLength)
        {
            // 参数校验必不可少
            if (intCount <= 0 || intLength <= 0 || intCount > intLength)
            {
                Debug.LogError($"无效参数:intCount({intCount})不能大于intLength({intLength}),且两者必须大于0");
                return new int[0];
            }

            HashSet<int> usedValues = new HashSet<int>();
            int[] returnValue = new int[intCount];
            int index = 0;
            // 设置最大尝试次数,防止极端情况陷入循环
            int maxAttempts = intCount * 10;
            int attempts = 0;

            while (index < intCount && attempts < maxAttempts)
            {
                int randomValue = Random.Range(0, intLength);
                // HashSet.Add()会自动判断是否重复,重复返回false
                if (usedValues.Add(randomValue))
                {
                    returnValue[index] = randomValue;
                    index++;
                }
                attempts++;
            }

            // 如果尝试次数耗尽仍未凑够,抛出错误提示
            if (index < intCount)
            {
                Debug.LogError($"无法生成足够的唯一整数,尝试次数已达上限");
                return new int[0];
            }

            return returnValue;
        }
    }
}

三、关键注意事项

  • 必须加参数校验:在函数开头就拦截非法参数,从根源避免无效调用;
  • 注意随机数范围:Unity的Random.Range(min, max)是左闭右开的,要生成0到intLength-1的数,必须写Random.Range(0, intLength);
  • 优先选洗牌法:当intCount接近intLength时,洗牌法的效率远高于重复检查法,不会出现循环次数过多的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:17:59