在Unity(C#)中的随机生成对象

3

你好,我在制作我的第一个2D Unity游戏,现在有以下代码。我有3个不同的游戏对象(称之为a、b、c),它们都在名为arrows的数组中,我想知道哪一个被生成了(这样我就可以在另一个函数中使用它)并从场景中删除先前的对象。现在它只是每隔5秒在另一个对象上生成一个游戏对象,我不知道它随机生成了其中的哪一个。有什么想法吗?

public GameObject[] arrows;
public float interval = 5;

// Use this for initialization
void Start()
{
    StartCoroutine(SpawnArrow());
}
public IEnumerator SpawnArrow()
{
    WaitForSeconds delay = new WaitForSeconds(interval);
    while (true)
    {
        GameObject prefab = arrows[UnityEngine.Random.Range(0, arrows.Length)];
        GameObject clone = Instantiate(prefab, new Vector3(0.02F, 2.18F, -1), Quaternion.identity);
        yield return delay;


    }
}`

你只需要将创建的对象作为参数使用。在while循环中,你可以加入 YourOtherFunction(clone)。如果这不是你想要的,请提供更多关于你尝试做什么的细节。在你的代码示例中也包括其他函数。 - Scott Chamberlain
另外,如果您在询问有关Unity的问题,则需要在您的问题上放置[tag:Unity3d]标签。否则,您可能会得到不适用于Unity的答案。 - Scott Chamberlain
2个回答

3
为了追踪您实例化的对象,您可以创建一个 GameObjectList,然后当您实例化一个对象时,您可以将它添加到 List 中。然后,您可以使用该列表中的任何 GameObject 来执行所需的操作。
public GameObject[] arrows;
public float interval = 5;
private List<GameObject> myObjects = new List<GameObject>();

// Use this for initialization
void Start()
{
    StartCoroutine(SpawnArrow());
}
public IEnumerator SpawnArrow()
{
    WaitForSeconds delay = new WaitForSeconds(interval);
    while (true)
    {
        GameObject prefab = arrows[UnityEngine.Random.Range(0, arrows.Length)];
        GameObject clone = Instantiate(prefab, new Vector3(0.02F, 2.18F, -1), Quaternion.identity);

        //Add the object to the list
        myObjects.Add(clone);

        yield return delay;


    }
}

针对这种生成对象的情况,最好使用InvokeRepeating。您可以传递它的重复速率和想要启动的时间。有关InvokeRepeating的更多信息 以下是如何使用InvokeRepeating的示例。
public GameObject[] arrows;
public float interval = 5;
private List<GameObject> myObjects = new List<GameObject>();

// Use this for initialization
void Start()
{
    InvokeRepeating("SpawnArrow", 0f, interval);
}

void SpawnArrow()
{
    //Check if there's something in the list
    if (myObjects.Count > 0)
    {
        //Destroy the last object in the list.
        Destroy(myObjects.Last());

        //Remove it from the list.
        myObjects.RemoveAt(myObjects.Count - 1);
    }

    GameObject prefab = arrows[UnityEngine.Random.Range(0, arrows.Length)];
    GameObject clone = Instantiate(prefab, new Vector3(0.02F, 2.18F, -1), Quaternion.identity);

    //Add the object to the list
    myObjects.Add(clone);

}

你可以通过执行Destroy(myObjects.Last());来销毁列表中上一个生成的对象,该方法将返回列表中的最后一个对象并销毁它。然后,您也应该从列表中删除该对象myObjects.RemoveAt(myObjects.Count - 1);


谢谢。我该如何知道最后一次生成的对象是什么(例如:如果生成了对象a,则使用它...),以及如何知道之前生成的对象,以便从场景中销毁它?(现在我正在使用InvokeRepeating代码):D - Klemen Škrlj
@KlemenŠkrlj 我在我的答案末尾添加了如何实现它的内容。 - I.B
这两行代码应该放在哪里?(我知道...我是个新手)它说我需要添加System.Linq,但当我运行它时,它显示:InvalidOperationException: Operation is not valid due to the current state of the object System.Linq.Enumerable.Last[GameObject] (IEnumerable`1 source)。 - Klemen Škrlj
@KlemenŠkrlj 我编辑了我的答案,你可以试试这样做,同时你需要在脚本顶部添加 using System.Linq; - I.B
既然你什么都知道,最后一个问题:我该如何检查它生成了哪个对象?我该如何将其实现到if语句中? - Klemen Škrlj
@KlemenŠkrlj 你可以通过检查物体的名称来知道生成的对象。你的 clone 值将保存刚刚生成的 GameObject,因此你可以执行 clone.name,然后将其与某个值进行比较。如果您详细描述您想要完成的操作并发布新问题,则会更容易提供帮助 :) - I.B

-2

我不知道这会有多大帮助,但是您是否尝试将每个箭头作为一个对象进行处理,然后将该对象返回给需要它的方法。

public GameObject SpawnArrow(<some params>){
    GameObject prefab = arrows[UnityEngine.Random.Range(0, arrows.Length)];
    while(interval > 0){
        if(interval = 0){
            prefab = arrows[UnityEngine.Random.Range(0, arrows.Length)];
            GameObject clone = Instantiate(prefab, new Vector3(0.02F, 2.18F, -1), Quaternion.identity);
        } else {
            System.Threading.Thread.sleep(1000) // wait for the second.
            interval = interval - 1;
        }
    }
    return prefab;
}

IDK Unity - 从未使用过,但您需要重写该函数以返回箭头对象(而不是延迟对象)到调用函数。当然,上述代码应被视为不起作用的伪代码,因为我不使用Unity。但要点就是找到一种更好的方法在一个可以返回箭头的方法中生成它。


在Unity中不是这样工作的,Instantiate将在当前场景中生成一个GameObjectyield return delay;的作用是等待指定时间后再继续执行。 - I.B
我又编辑了一下 - 但是我不懂Unity,只会C#。我在编辑中解释了这一点。 - Mitchell Urgero
1
在Unity项目中,永远不要调用System.Threading.Thread.Sleep - Scott Chamberlain
@ScottChamberlain - 感谢您提供的信息!就像我在帖子中所说的那样 - 我不使用Unity - 因此应该将代码视为伪代码。我感谢您的信息并会牢记在心! - Mitchell Urgero
1
@MitchellUrgero 如果你不确定,就不应该回答问题,如果你不了解Unity,那么你的回答可能会让提问者感到困惑,或者是错误的答案。 - Sxntk
@Sxntk 虽然你说得没错 - 我对C#有足够的了解,至少可以尝试帮忙(我本来想用评论的,但我是一个非常新的、轻量级的stackoverflow用户,所以不能用),所以不幸的是我用了一个答案 :( 下次我会努力做得更好。谢谢! - Mitchell Urgero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接