如何在 Unity 中的特定位置生成预制件,然后删除该值?

Posted

技术标签:

【中文标题】如何在 Unity 中的特定位置生成预制件,然后删除该值?【英文标题】:How can I spawn a prefab in Unity in a specific position and then delete that value? 【发布时间】:2021-06-05 00:59:50 【问题描述】:

我正在制作一个游戏,一个迷宫,你必须在其中收集 10 个拾取物才能赢得游戏。其中一些拾音器将始终在相同的位置,但还有一些会在开始时使用 for 循环在随机位置生成(之前在代码中声明了所有可能的选项)。这个想法是,当一个元素被生成时,包含该位置的 Vector3 必须从 List 中删除,因此它不能在同一位置再次生成。

我试过用数组来做这件事,但我不能轻易地删除那个值,所以我决定试试 Lists。我发现this post 旨在使用列表并提供解决方案,但是当我尝试时它不起作用。没有生成拾取器,但我无法找到错误。

代码如下:

public GameObject pointPrefab;

List<Vector3> positions = new List<Vector3>();

public Vector3[] vectorPositions =

    new Vector3 (237.05f, 0,- 34.02419f),   // Position 0
    // ... More positions here
    new Vector3 (207.1207f, 0, -74.42f),    // Position 8
;



void Start()

    positions.Add(new Vector3(237.05f, 0, -34.02419f));
    // ... More positions here
    positions.Add(new Vector3(207.1207f, 0, -74.42f));


    for (int i = 0; i < 6; i++)
    
        spawnItem();
    


void spawnItem()

    int index = selectRandom();
    Vector3 vector = RemoveAndGet(positions, index);
    Instantiate(pointPrefab, vector, Quaternion.identity);


int selectRandom()

    return Random.Range(0, positions.Count);


public T RemoveAndGet<T>(IList<T> list, int index)

    lock (list)
    
        T value = list[index];
        list.RemoveAt(index);
        return value;
    

此外,您还看到了一个名为 vectorPositions 的数组。我想声明该数组中的所有 Vector3,然后只需使用 position.AddRange(vectorPosition) 将它们全部分配给 List(这对我来说更容易阅读)。但这也不起作用(好吧,我不知道它是否起作用,因为没有生成拾取器)

希望你能帮帮我,我看不出这里出了什么问题。

谢谢!

【问题讨论】:

检查你的程序是否工作以及它如何工作、出现什么问题以及甚至没有开始工作的最佳方法是使用 PRINT() 或 DEBUG.LOG() 调试你的程序的 我现在去看看调试的时候有没有明白的,谢谢分享! HashSetDictionary 可能更适合这里。 Debug.Log() 应该打印我在控制台中作为参数输入的内容,对吧?因为 spawnItem() 没有被初始化。我也要检查 HashSet 和 Dictionary。 你为什么不“洗牌”列表并选择 6 个连续的值呢?真的需要从原始列表中删除它们吗?为什么lock?我没有看到涉及任何多线程,所以这似乎毫无意义。你也知道你可以使用例如positions = vectorPositions.ToList();positions = new List&lt;Vector3&gt;(vectorPositions); ... 【参考方案1】:

有多种方法可以做到这一点。例如。你可以简单地写

positions = vectorPositions.ToList(); 

也可以

positions = new List<Vector3>(vectorPositions);

但是,为什么还要创建数组的副本?

你也可以做到

public List<Vector3> vectorPositions = new List<Vector3> ... ;

如果您确实需要在运行时删除项目。


无论如何,您还可以使用 Linq OrderByRandom.value 作为排序标准和 Take 更轻松地生成 6 个随机元素,以便从该随机列表中获取前 6 个连续条目

using System.Linq;

...

var sixRandomPositions = vectorPositions.OrderBy(p => Random.value).Take(6);
foreach(var position in sixRandomPositions)

    Instantiate(pointPrefab, position, Quaternion.identity);

不改变原来的vectorPositions

【讨论】:

以上是关于如何在 Unity 中的特定位置生成预制件,然后删除该值?的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Unity 编辑器中加载预制件

Unity - 动画将游戏对象从其产生的位置移开?

unity如何删除一堆预制物体

Unity2D:在订单中禁用实例化的预制件

如何在Unity的水平布局中将特定的孩子放在前面

Unity3D日常开发生成预制体,并且预制体自动销毁