如何将3个GameObject随机分配到3个指定位置且无重复?
基于Random.Range的基础实现
你的需求核心是保证每个位置仅被分配一次,我们可以通过维护临时待选位置列表的方式实现,每次从剩余位置中随机选取后移除已用位置,避免重复:
using System.Collections.Generic; using UnityEngine; public class RandomPosAssign : MonoBehaviour { public GameObject[] myObjs; public Vector3[] myPos; void Start() { // 前置校验,避免数组长度不匹配报错 if (myObjs.Length != myPos.Length) { Debug.LogError("物体数组和位置数组长度不一致,请检查配置"); return; } List<Vector3> unusedPos = new List<Vector3>(myPos); for (int i = 0; i < myObjs.Length; i++) { // Random.Range整数重载为左闭右开,取[0, unusedPos.Count)刚好覆盖所有剩余位置索引 int randomIdx = Random.Range(0, unusedPos.Count); myObjs[i].transform.position = unusedPos[randomIdx]; // 移除已分配位置,避免后续重复抽取 unusedPos.RemoveAt(randomIdx); } } }
更优实现方案:Fisher-Yates洗牌算法
上面的方案用到了List.RemoveAt,数组长度较大时会产生O(n²)的时间复杂度,性能较差。更推荐用原地乱序的Fisher-Yates洗牌算法,时间复杂度仅为O(n),内存占用也更低:
using UnityEngine; public class RandomPosAssign : MonoBehaviour { public GameObject[] myObjs; public Vector3[] myPos; void Start() { if (myObjs.Length != myPos.Length) { Debug.LogError("物体数组和位置数组长度不一致,请检查配置"); return; } // 原地打乱位置数组 for (int i = myPos.Length - 1; i > 0; i--) { int randomIdx = Random.Range(0, i + 1); // 交换当前索引与随机索引的位置 (myPos[i], myPos[randomIdx]) = (myPos[randomIdx], myPos[i]); } // 按顺序分配已乱序的位置即可,天然不重复 for (int i = 0; i < myObjs.Length; i++) { myObjs[i].transform.position = myPos[i]; } } }
注意事项
Random.Range的整数重载为左闭右开,如果最大值填写为数组/列表长度,不会产生索引越界问题- 如果后续需要保留原始位置数组的顺序,只需提前拷贝一份临时数组做乱序操作即可
内容的提问来源于stack exchange,提问作者Vika
相关产品推荐
相关产品推荐

