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

如何用循环精简代码且避免重复随机数?18个GameObject指定Z轴位姿设置求助

解决方案:为18个GameObject分配不重复的Z轴随机位置

看起来你需要给18个障碍物体分配唯一的Z轴位置(都是60的倍数),还要用循环精简代码、避免重复随机数。我帮你整理了两种可行的实现方式,代码简洁且逻辑清晰:

方式一:用List处理(推荐,代码更简洁)

利用C#的List来管理可用的位置索引,它自带的RemoveAt方法可以轻松移除已使用的索引,避免重复:

using UnityEngine;
using System.Collections.Generic;

public class HurdlePlacement : MonoBehaviour
{
    GameObject[] hurdles;
    List<int> availablePositionIndices;

    void Start()
    {
        // 找到所有标记为"Hurdles"的物体
        hurdles = GameObject.FindGameObjectsWithTag("Hurdles");
        
        // 先做个校验:确保找到的物体数量正好是18个,避免后续逻辑出错
        if (hurdles.Length != 18)
        {
            Debug.LogError("找到的Hurdles数量不是18个!请检查场景中的物体标签");
            return;
        }

        // 初始化可用位置索引:0到17,对应Z值0、60、120...1020(17*60)
        availablePositionIndices = new List<int>();
        for (int i = 0; i < 18; i++)
        {
            availablePositionIndices.Add(i);
        }

        // 循环给每个障碍分配位置
        foreach (GameObject hurdle in hurdles)
        {
            // 从剩余可用的索引里随机选一个
            int randomListIndex = Random.Range(0, availablePositionIndices.Count);
            int selectedIndex = availablePositionIndices[randomListIndex];
            
            // 计算对应的Z轴位置:索引*60
            float targetZ = selectedIndex * 60f;
            // 设置物体位置(X、Y保持0,你可以根据需求修改)
            hurdle.transform.position = new Vector3(0f, 0f, targetZ);

            // 把已使用的索引从列表中移除,避免重复分配
            availablePositionIndices.RemoveAt(randomListIndex);
        }
    }
}

方式二:用数组手动处理(适合不想用List的场景)

如果你不想引入List,也可以用数组自己实现移除元素的逻辑:

using UnityEngine;

public class HurdlePlacement : MonoBehaviour
{
    GameObject[] hurdles;
    int[] availablePositionIndices;

    void Start()
    {
        hurdles = GameObject.FindGameObjectsWithTag("Hurdles");
        
        if (hurdles.Length != 18)
        {
            Debug.LogError("找到的Hurdles数量不是18个!请检查场景中的物体标签");
            return;
        }

        // 初始化可用索引数组
        availablePositionIndices = new int[18];
        for (int i = 0; i < availablePositionIndices.Length; i++)
        {
            availablePositionIndices[i] = i;
        }

        foreach (GameObject hurdle in hurdles)
        {
            int randomArrayIndex = Random.Range(0, availablePositionIndices.Length);
            int selectedIndex = availablePositionIndices[randomArrayIndex];
            
            float targetZ = selectedIndex * 60f;
            hurdle.transform.position = new Vector3(0f, 0f, targetZ);

            // 移除已使用的索引,更新可用数组
            RemoveElementFromArray(ref availablePositionIndices, randomArrayIndex);
        }
    }

    // 辅助方法:从数组中移除指定索引的元素
    void RemoveElementFromArray(ref int[] array, int indexToRemove)
    {
        int[] newArray = new int[array.Length - 1];
        int newArrayIndex = 0;
        for (int i = 0; i < array.Length; i++)
        {
            if (i != indexToRemove)
            {
                newArray[newArrayIndex] = array[i];
                newArrayIndex++;
            }
        }
        array = newArray;
    }
}

核心逻辑说明

  1. 不重复随机数的实现:我们不是直接随机生成Z值,而是先维护一个「可用位置索引列表/数组」,每次选完一个索引后就把它移除,这样后续永远不会选到重复的索引,自然也就不会有重复的Z位置。
  2. 循环精简代码:用foreach遍历所有障碍物体,代替手动写18次赋值语句,代码更简洁,而且如果后续物体数量变化,只要调整索引范围就能适配。
  3. Z值计算:因为你需要的Z值是0,60,120...,正好是索引*60,所以用索引来计算Z值非常方便,不需要额外维护一个Z值数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:17:26