You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity倒计时计时器重置Bug求助:实现每个RecipeTemplate独立计时

问题解决:Unity实现独立倒计时计时器

问题根源

你写的DeliveryManagerUI里的UptadeVisual(注意拼写错误,应为UpdateVisual)方法每次触发时,会销毁容器内所有已生成的recipe实例,再重新遍历所有等待中的RecipeSO生成新实例。这直接导致所有旧计时器UI被销毁重建,自然所有计时器都会被重置。

修复方案

核心思路是停止全删重建的逻辑,改为只同步新增和移除的条目,让每个UI实例保留独立的计时器状态。

1. 重构DeliveryManagerUI代码

添加一个字典来维护RecipeSO和对应UI实例的映射,精准跟踪需要添加或移除的UI:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DeliveryManagerUI : MonoBehaviour
{
    [SerializeField] private Transform container;
    [SerializeField] private Transform recipeTemplate;

    // 存储每个Recipe对应的UI实例
    private Dictionary<RecipeSO, Transform> recipeUIMap = new Dictionary<RecipeSO, Transform>();

    private void Awake() {
        recipeTemplate.gameObject.SetActive(false);
    }

    private void Start() {
        DeliveryManager.Instance.OnRecipeSpawned += DeliveryManager_OnRecipeSpawned;
        DeliveryManager.Instance.OnRecipeCompeted += DeliveryManager_OnRecipeCompleted;

        // 初始化已有的等待订单UI
        InitializeExistingRecipes();
    }

    private void InitializeExistingRecipes()
    {
        foreach (RecipeSO recipeSO in DeliveryManager.Instance.GetWaitingWave1RecipeSOList())
        {
            CreateRecipeUI(recipeSO);
        }
    }

    private void DeliveryManager_OnRecipeSpawned(object sender, System.EventArgs e) {
        SyncRecipeUI();
    }

    private void DeliveryManager_OnRecipeCompleted(object sender, System.EventArgs e) {
        SyncRecipeUI();
    }

    // 同步UI与当前等待订单列表
    private void SyncRecipeUI()
    {
        List<RecipeSO> currentWaitingRecipes = DeliveryManager.Instance.GetWaitingWave1RecipeSOList();
        HashSet<RecipeSO> currentRecipeSet = new HashSet<RecipeSO>(currentWaitingRecipes);

        // 移除已完成订单的UI
        List<RecipeSO> toRemove = new List<RecipeSO>();
        foreach (var kvp in recipeUIMap)
        {
            if (!currentRecipeSet.Contains(kvp.Key))
            {
                Destroy(kvp.Value.gameObject);
                toRemove.Add(kvp.Key);
            }
        }
        foreach (RecipeSO recipe in toRemove)
        {
            recipeUIMap.Remove(recipe);
        }

        // 添加新增订单的UI
        foreach (RecipeSO recipeSO in currentWaitingRecipes)
        {
            if (!recipeUIMap.ContainsKey(recipeSO))
            {
                CreateRecipeUI(recipeSO);
            }
        }
    }

    // 创建单个订单UI
    private void CreateRecipeUI(RecipeSO recipeSO)
    {
        Transform recipeTransform = Instantiate(recipeTemplate, container);
        recipeTransform.gameObject.SetActive(true);
        recipeTransform.GetComponent<DeliveryManagerSingleUI>().SetRecipeSO(recipeSO);
        recipeUIMap.Add(recipeSO, recipeTransform);
    }
}

2. 优化DeliveryManager事件(推荐)

为了更高效,建议修改DeliveryManager的事件,让事件携带具体的RecipeSO,避免每次全量对比列表:

// 在DeliveryManager中定义自定义事件参数
public class RecipeSpawnedEventArgs : System.EventArgs
{
    public RecipeSO RecipeSO { get; set; }
}

public class RecipeCompletedEventArgs : System.EventArgs
{
    public RecipeSO RecipeSO { get; set; }
}

// 修改事件声明
public event System.EventHandler<RecipeSpawnedEventArgs> OnRecipeSpawned;
public event System.EventHandler<RecipeCompletedEventArgs> OnRecipeCompeted;

// 生成订单时触发事件
OnRecipeSpawned?.Invoke(this, new RecipeSpawnedEventArgs { RecipeSO = spawnedRecipe });

// 完成订单时触发事件
OnRecipeCompeted?.Invoke(this, new RecipeCompletedEventArgs { RecipeSO = completedRecipe });

然后更新DeliveryManagerUI的事件处理逻辑,直接处理单个订单:

private void DeliveryManager_OnRecipeSpawned(object sender, RecipeSpawnedEventArgs e) {
    CreateRecipeUI(e.RecipeSO);
}

private void DeliveryManager_OnRecipeCompleted(object sender, RecipeCompletedEventArgs e) {
    if (recipeUIMap.TryGetValue(e.RecipeSO, out Transform uiTransform))
    {
        Destroy(uiTransform.gameObject);
        recipeUIMap.Remove(e.RecipeSO);
    }
}

3. DeliveryManagerSingleUI无需大改

原代码的计时器逻辑没问题,现在每个UI实例只会被创建一次,SetRecipeSO也只会调用一次,计时器会保持独立运行。

关键说明

  • 解决问题的核心是停止全删重建UI,改用映射关系跟踪每个订单对应的UI实例,只增删变化的条目,从而保留每个计时器的独立状态。
  • 传递具体RecipeSO的事件能大幅提升效率,避免不必要的列表对比操作。

内容的提问来源于stack exchange,提问作者Felix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:56:30