C# 如何从列表中删除当前播放索引项,但变量“I”现在是1而不是0?
在脚本中:C# 如何从列表中删除当前播放索引项,但变量“I”现在是1而不是0?,c#,unity3d,C#,Unity3d,在脚本中: using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class NaviDialogue : MonoBehaviour { public ObjectsManipulation op; public bool scaling = true; public Scalin
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NaviDialogue : MonoBehaviour
{
public ObjectsManipulation op;
public bool scaling = true;
public Scaling scale;
public ConversationTrigger conversationTrigger;
private bool ended = false;
private bool startConversation = false;
private void Update()
{
if (scaling == true && DOFControl.hasFinished == true)
{
DOFControl.hasFinished = false;
scaling = false;
op.Scaling();
PlayerController.disablePlayerController = true;
ConversationTrigger.conversationsToPlay.Add(0);
ConversationTrigger.conversationsToPlay.Add(1);
ConversationTrigger.conversationsToPlay.Add(2);
StartCoroutine(conversationTrigger.PlayConversations());
}
}
在ConversationTrigger的顶部:
public static List<int> conversationsToPlay = new List<int>();
问题是,在PlayConversations方法中,now I的值为1,因此它将播放下一个最后一项。因此,如果有3个项目,它将播放第一个和最后一个,但不会播放中间的项目。您不应该修改当前正在迭代的集合。您遇到的问题是原因之一。在您的情况下,有几个选项,一个简单的解决方案是复制对话列表,同时清除原始列表:
public IEnumerator PlayConversations()
{
var conversations = conversationsToPlay.ToArray(); // Copy the list
conversationsToPlay.Clear(); // Immediately clear the original list
for (int i = 0; i < conversations.Length; i++) // iterate over the array
{
// Now you also don't need to remove items anymore,
// since you already cleared the list
yield return StartCoroutine(PlayConversation(conversations[i]));
}
}
在使用第二个示例时,您也可以使用队列而不是对话列表,因为队列是专门为先进先出访问而设计的 您不应该修改当前正在迭代的集合。您遇到的问题是原因之一。在您的情况下,有几个选项,一个简单的解决方案是复制对话列表,同时清除原始列表:
public IEnumerator PlayConversations()
{
var conversations = conversationsToPlay.ToArray(); // Copy the list
conversationsToPlay.Clear(); // Immediately clear the original list
for (int i = 0; i < conversations.Length; i++) // iterate over the array
{
// Now you also don't need to remove items anymore,
// since you already cleared the list
yield return StartCoroutine(PlayConversation(conversations[i]));
}
}
在使用第二个示例时,您也可以使用队列而不是对话列表,因为队列是专门为先进先出访问而设计的 如果您没有维护订单的业务需求,那么在计划删除项目时,始终以相反的顺序迭代集合。这样,您可以在不中断数组顺序的情况下删除项。所以这里
public IEnumerator PlayConversations()
{
for (int i = conversationsToPlay.Count-1; i >=0; i++)
{
yield return StartCoroutine(PlayConversation(conversationsToPlay[i]));
}
}
此方法通常适用于从集合中删除某些内容的所有情况。然而,另一方面,删除Playconversation方法中的对话只是一种不好的做法。您将得到难以维护的代码。用专门用于此目的的方法将其移除。否则,您违反了SRP如果您没有维护订单的业务需求,那么当您计划删除项目时,请始终以相反的顺序迭代集合。这样,您可以在不中断数组顺序的情况下删除项。所以这里
public IEnumerator PlayConversations()
{
for (int i = conversationsToPlay.Count-1; i >=0; i++)
{
yield return StartCoroutine(PlayConversation(conversationsToPlay[i]));
}
}
此方法通常适用于从集合中删除某些内容的所有情况。然而,另一方面,删除Playconversation方法中的对话只是一种不好的做法。您将得到难以维护的代码。用专门用于此目的的方法将其移除。否则,您将违反SRP如果没有这一行“conversationsToPlay.Removeindex;”会发生什么。你试过这个吗?变量“conversations”在哪里?好吧,不用for循环,可以在计数>0时始终播放0,然后在DialogEnd时删除0。另外,一般的指导原则是,当您计划从集合中删除对象时,从结尾到结尾进行迭代。如果没有这一行“conversationsToPlay.Removeindex;”,会发生什么。你试过这个吗?变量“conversations”在哪里?好的,您可以在count>0时始终播放0,然后在dialogend时删除0,而不是for循环。另外,一般的指导原则是,当您计划从集合中删除对象时,从头到脚进行迭代。
public IEnumerator PlayConversations()
{
while (conversationsToPlay.Count > 0)
{
// Better remove the item right here, close to the loop condition.
// Makes things easier to understand.
var conversationIndex = conversationsToPlay[0];
conversationsToPlay.RemoveAt(0);
yield return StartCoroutine(PlayConversation(conversationIndex));
}
}
public IEnumerator PlayConversations()
{
for (int i = conversationsToPlay.Count-1; i >=0; i++)
{
yield return StartCoroutine(PlayConversation(conversationsToPlay[i]));
}
}