目前正在撰寫一個構建 HUD 的腳本,用于測驗專案中的某些功能。它會自動構建按鈕,其中一個有效,而另一個給出標題中指示的錯誤和下面的錯誤訊息。
當被手動放置在場景中的按鈕呼叫時,按鈕呼叫的函式起作用,這表明問題不在于函式本身,而在于按鈕的構建方式。
腳本編譯成功并在編輯器中正確呈現。單擊單選按鈕(構建給出錯誤的按鈕)可以正常作業,構建按鈕并運行除錯日志。
單擊單選按鈕生成的“下一首歌曲”按鈕時會發生錯誤。
這是錯誤:
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <6073cf49ed704e958b8a66d540dea948>:0)
TestHUD <>c__DisplayClass12_0.<BuildActions>b__0 () (at Assets/Scripts/TestHUD.cs:86)
UnityEngine.Events.InvokableCall.Invoke () (at <f1212ad1dec44ce7b7147976b91869c3>:0)
UnityEngine.Events.UnityEvent.Invoke () (at <f1212ad1dec44ce7b7147976b91869c3>:0)
UnityEngine.UI.Button.Press () (at Library/PackageCache/[email protected]/Runtime/UI/Core/Button.cs:70)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at Library/PackageCache/[email protected]/Runtime/UI/Core/Button.cs:114)
UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at Library/PackageCache/[email protected]/Runtime/EventSystem/ExecuteEvents.cs:57)
UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents EventFunction`1[T1] functor) (at Library/PackageCache/[email protected]/Runtime/EventSystem/ExecuteEvents.cs:272)
UnityEngine.EventSystems.EventSystem:Update() (at Library/PackageCache/[email protected]/Runtime/EventSystem/EventSystem.cs:501)
這是除錯日志
buttonActions 的長度為 1。
創建的功能按鈕
這是當前存在的腳本:
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class TestHUD : MonoBehaviour
{
GameObject testHUD;
public List<TestHUDPanel> testHUDPanels = new();
public GameObject sectionPanel;
public GameObject functionPanel;
public GameObject sectionPrefab;
public GameObject functionPrefab;
//Color32 activeColor = new Color32(255, 201, 191, 255);
//Color32 inactiveColor = new Color32(191, 255, 241, 255);
SoundManager soundManager;
public class TestHUDPanel
{
public string name;
public GameObject linkedObject;
public GameObject panelObject;
public List<Action> buttonActions = new();
public List<string> buttonLabels = new();
public TestHUDPanel(string panelName)
{
name = panelName;
}
public void AddButton(string buttonName, Action buttonFunc)
{
buttonActions.Add(buttonFunc);
buttonLabels.Add(buttonName);
}
}
private void Awake()
{
testHUD = gameObject;
soundManager = GameObject.Find("SoundManager").GetComponent<SoundManager>();
}
private void Start()
{
BuildPanelList();
BuildPanels();
}
public void BuildPanelList()
{
testHUDPanels.Add(new TestHUDPanel("Radio"));
testHUDPanels[0].AddButton("Next Song", soundManager.PlayNextSong);
testHUDPanels.Add(new TestHUDPanel("Typing"));
testHUDPanels.Add(new TestHUDPanel("Audio"));
}
public void BuildPanels()
{
foreach (TestHUDPanel panel in testHUDPanels)
{
GameObject panelObject = Instantiate(sectionPrefab);
panelObject.transform.SetParent(sectionPanel.transform);
Button button = panelObject.GetComponent<Button>();
panelObject.GetComponentInChildren<TextMeshProUGUI>().text = panel.name;
button.onClick.AddListener(() => BuildActions(panel));
}
}
public void BuildActions(TestHUDPanel panel)
{
for (int i = 0; i < panel.buttonActions.Count; i )
{
GameObject panelObject = Instantiate(functionPrefab);
panelObject.transform.SetParent(functionPanel.transform);
Button button = panelObject.GetComponent<Button>();
panelObject.GetComponentInChildren<TextMeshProUGUI>().text = panel.buttonLabels[i];
Debug.Log(string.Format("Length of buttonActions is {0}, ", panel.buttonActions.Count));
>>> THIS IS LINE 86 <<< : button.onClick.AddListener(() => panel.buttonActions[i]());
Debug.Log("Function button created");
}
}
}
uj5u.com熱心網友回復:
正如漢斯指出的那樣,問題源于一個捕獲的變數。
當我們的變數向上迭代時,lambda 運算式沒有正確捕獲它,因此給出了上面提到的錯誤。
下面是更新后的 BuildActions 函式,其中有一個臨時變數,它臨時保存 i 的值以允許它在 lambda 運算式中使用,即使迭代器在賦值和執行之間更改值,臨時變數仍將允許 lambda 運算式正常運行。
public void BuildActions(TestHUDPanel panel)
{
for (int i = 0; i < panel.buttonActions.Count; i )
{
var tempIDX = i;
GameObject panelObject = Instantiate(functionPrefab);
panelObject.transform.SetParent(functionPanel.transform);
Button button = panelObject.GetComponent<Button>();
panelObject.GetComponentInChildren<TextMeshProUGUI>().text = panel.buttonLabels[i];
button.onClick.AddListener(() => panel.buttonActions[tempIDX]());
}
}
我還將鏈接 lambda 運算式中捕獲的變數的檔案以進行進一步解釋。
捕獲 lambda 運算式中的外部變數和變數范圍
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/489891.html
上一篇:接受在反應中的檔案型別中不起作用