Unity C#传递Action参数时确认窗口方法重复执行问题排查
问题分析与解决方案
核心原因
每次调用ThrowAConfirmScreen方法时,都会给confirmButton和cancelButton重复添加点击监听器。Unity的UI按钮点击事件是多播委托,每次AddListener都会往委托列表中追加新的回调方法,而你点击取消时只是隐藏窗口,并没有移除这些已添加的监听器。当多次取消再点击确认时,所有累积的监听器都会被触发,导致传入的func执行次数等于之前取消的次数。
解决方案
方案1:每次绑定前移除旧监听器
在添加新的点击监听器前,先清除按钮上已有的所有监听器,避免重复绑定:
public void ThrowAConfirmScreen(string msg, Action func) { confirmField.SetActive(true); confirmText.text = msg; // 清除按钮上的所有旧监听器 confirmButton.onClick.RemoveAllListeners(); cancelButton.onClick.RemoveAllListeners(); confirmButton.onClick.AddListener(() => { func(); confirmField.SetActive(false); }); cancelButton.onClick.AddListener(() => { confirmField.SetActive(false); }); }
方案2:初始化时单次绑定,复用逻辑
更优雅的方式是只在初始化阶段绑定一次监听器,通过变量存储当前要执行的回调,避免重复绑定:
private Action _currentConfirmAction; void Awake() { // 仅在初始化时绑定一次监听器 confirmButton.onClick.AddListener(OnConfirmClicked); cancelButton.onClick.AddListener(OnCancelClicked); confirmField.SetActive(false); } public void ThrowAConfirmScreen(string msg, Action func) { _currentConfirmAction = func; confirmText.text = msg; confirmField.SetActive(true); } private void OnConfirmClicked() { _currentConfirmAction?.Invoke(); confirmField.SetActive(false); _currentConfirmAction = null; // 执行后清空,避免残留 } private void OnCancelClicked() { confirmField.SetActive(false); _currentConfirmAction = null; }
为什么之前的尝试无效
不管使用箭头函数、单独声明函数还是替换为Func<>,只要每次调用ThrowAConfirmScreen都执行AddListener,就会不断往按钮的委托列表中追加新的回调,因为Unity的AddListener不会覆盖已有的委托方法,只会累加。
内容的提问来源于stack exchange,提问作者crybaby
相关产品推荐
相关产品推荐

