【问题标题】:How to get access to my index from another function?如何从另一个函数访问我的索引?
【发布时间】:2020-01-14 11:19:43
【问题描述】:

我想在我的函数更新中从我的列表 Prefab[] 中销毁对象,但我还没有弄清楚如何在另一个函数中访问列表的索引。你知道我该怎么做吗?

这是我的代码:

public GameObject[] Prefab;
public Transform[] spawnPoint;
public Transform player;
public AudioClip[] sonAnimaux ;
private int i = 0;
private int j = 0;
private int k = 0;
private float delay = 3f;

void OnTriggerEnter(Collider other) {
    // fonction on l'on fait apparaitre les objets de la liste selon son empty

    while (i<Prefab.Length && j < spawnPoint.Length && k < sonAnimaux.Length )  {

        AudioSource audio = GetComponent<AudioSource>();
        Instantiate(Prefab[i] , spawnPoint[j].position, spawnPoint[j].rotation);
        audio.clip = sonAnimaux[k];
        audio.Play();
        i++;
        j++;
        k++;
    }
}

void Update() {
    Destroy(Prefab[i],delay);
    Debug.Log("The object" + Prefab[i]);
}

我想销毁 Prefab[i] 但我不知道如何在另一个函数中获取我的索引列表。

【问题讨论】:

  • 这取决于你想从哪里调用更新。您应该可以将其作为参数传递。
  • 我希望我的 Prefab[i] 对象在 3 秒后被销毁,所以我只需在我的更新函数参数中传递 prefab[] 列表?像这样 ? :无效更新(预制[i])? @PalleDue
  • @kehalS:更像void Update(int i)
  • 另外,销毁预制件和销毁预制件的新实例(克隆)是有区别的。
  • 为什么要在Udpate中这样做根本?只需在实际上应该销毁它的方法中执行它...当前i 是一个 field 所以访问它应该没有问题.. 我猜你宁愿遇到这个@987654325 的问题@ 没有您期望的值,请注意 Update 被称为每一帧,因此您的代码目前对我来说没有多大意义,因为已经在下一帧中您的 i 将无效,因为你已经销毁了那个对象

标签: c# list unity3d indexing


【解决方案1】:

从您的 cmets 的上下文来看,您想要实现的目标是在实例化后延迟销毁克隆。

正如其他人所建议的,Destroy 不需要从更新中调用,您需要实例化对象的引用。将 Destroy 与 Prefab 数组一起使用会破坏预制件。

public GameObject[] Prefab;
public Transform[] spawnPoint;
public Transform player;
public AudioClip[] sonAnimaux ;
private int i = 0;
private int j = 0;
private int k = 0;
private float delay = 3f;

void OnTriggerEnter(Collider other) {
    // fonction on l'on fait apparaitre les objets de la liste selon son empty

    while (i<Prefab.Length && j < spawnPoint.Length && k < sonAnimaux.Length )  {

        AudioSource audio = GetComponent<AudioSource>();

        // Get the instantiated GameObject's reference
        GameObject clone = Instantiate(Prefab[i] , spawnPoint[j].position, spawnPoint[j].rotation);
        // Queue the object for destruction
        Destroy(clone, delay);
        Debug.Log("The object" + Prefab[i]); // If you still need it, move your Log call

        audio.clip = sonAnimaux[k];
        audio.Play();
        i++;
        j++;
        k++;
    }
}

*立即将 GameObject 排队等待销毁似乎会使您当前的更新功能过时,因此为简洁起见,我将其删除。

【讨论】:

  • 如果我知道 Unity,我会怎么做 ;-) keHals:我认为你应该接受这个答案。
  • 你也不需要 i、j 和 k,因为三个集合中最小的一个会占上风。他们最终都是一样的。如果它们都是相同大小的集合,那么 for 循环就足够了。但是那里有一个次要问题,你总是到达同一个 AudioSource 并重新分配一个新的音频给它,它只会播放最后一个音频。
  • 更好的解决方案是将 AudioSource 放在预制件上,然后让它们在 Awake 上播放,因此需要分配和播放,它将自动完成。这也更有意义,因为音频将使用 3D 空间,而现在它全部位于该管理器对象上。
  • @Joe keHals wants to destroy the instantiated object 真的,对不起!
  • @Everts - 两者都是正确的,但我试图回答当前出现的问题,而不是提供代码审查。也许 keHals 对这些计数器有其他用途?
【解决方案2】:

总结我到目前为止所说的一切。

更新您的预制件以附加一个带有适当音频文件的 AudioSource。然后让他们在清醒状态下玩。这将消除对音频代码的需求。

还假设您拥有相同数量的预制件和生成点。

那么你就剩下:

public GameObject[] Prefab;
public Transform[] spawnPoint;
private float delay = 3f;

void OnTriggerEnter(Collider other) 
{
    for (int i = 0; i < Prefabs.Length; i++)
    {
        GameObject clone = Instantiate(Prefab[i], spawnPoint[i].position, spawnPoint[i].rotation);
        Destroy(clone, delay);
    }
}

如果您没有相同数量的预制件和生成点,那么您需要运行最小的集合以避免越界异常:

private int size;

void Awake()
{
    size = (Prefabs.Length < spawnPoint.Length) ? Prefabs.Length : spawnPoint.Length;
}

void OnTriggerEnter(Collider other) 
{
    for (int i = 0; i < size; i++)
    {
        GameObject clone = Instantiate(Prefab[i], spawnPoint[i].position, spawnPoint[i].rotation);
        Destroy(clone, delay);
    }
}

【讨论】:

    【解决方案3】:

    我不知道Unity,但我想Update 是一个虚方法,你不能改变参数。在这种情况下,您可以执行以下操作:

    public GameObject[] Prefab;
    public Transform[] spawnPoint;
    public Transform player;
    public AudioClip[] sonAnimaux ;
    private int i = 0;
    private int j = 0;
    private int k = 0;
    private float delay = 3f;
    
    private int indexToDelete = -1;
    
    void OnTriggerEnter(Collider other) {
        // fonction on l'on fait apparaitre les objets de la liste selon son empty
    
        while (i<Prefab.Length && j < spawnPoint.Length && k < sonAnimaux.Length )  {
    
            AudioSource audio = GetComponent<AudioSource>();
            Instantiate(Prefab[i] , spawnPoint[j].position, spawnPoint[j].rotation);
            indexToDelete = i;
            audio.clip = sonAnimaux[k];
            audio.Play();
            i++;
            j++;
            k++;
        }
    }
    
    void Update() {
        if (indexToDelete>=0 && indexToDelete<Prefab.Length)
        {
            Destroy(Prefab[indexToDelete], delay);
            Debug.Log("The object" + Prefab[indexToDelete]);
        }
    }
    

    这假设OnTriggerEnterUpdate 在同一个类中,因此它们可以共享成员indexToDelete 的值。否则你将不得不实现某种消息传递。

    【讨论】:

    • 这将破坏预制件,但不会破坏新实例。另外,既然您使用了延迟,为什么可以在触发方法中调用销毁时运行更新。这将尝试多次破坏同一个对象。但是由于您正在销毁预制件,因此克隆仍然存在。
    • 另外,indexToDelete、i、j 和 k 没有意义,因为它们是相同的值。
    • @Everts:我不想进入那个讨论,只是想展示一种修复 keHals 代码的方法。
    • @Everts:我认为其他索引可以在代码的其他地方更改,所以我介绍了一个不会更改的索引。
    • 另请注意:一旦元素仍然是Prefab数组的一部分..但具有值null..所以下一帧你试图做Destroy(null)并将得到一个例外。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 2020-10-23
    相关资源
    最近更新 更多