当前位置: 首页 > news >正文

【Unity笔记】Unity超时检测器开发:支持自定义重试次数与事件触发

在这里插入图片描述


在Unity游戏或应用开发中,我们经常会遇到需要检测超时的场景,比如:

  • 等待用户在限定时间内完成某个交互;
  • 等待网络请求或资源加载是否在规定时间内返回;
  • 控制AI角色等待某个事件发生,超时后执行备选逻辑。

在这些场景中,如果仅检测一次是否超时,可能不够灵活。因此,我们本篇博客将带你一步步开发一个可复用的 TimeoutDetector Unity组件,支持以下功能:

  • 自定义超时时间;
  • 超时后自动重新检测;
  • 支持设置最大重试次数;
  • 每次超时与最终失败都能触发 UnityEvent;
  • 可用于编辑器按钮中一键添加到 GameObject。

一、设计思路

我们希望 TimeoutDetector 具备如下能力:

  1. 计时:从调用 StartDetection() 开始倒计时,若超出 timeoutDuration 则触发超时逻辑;
  2. 重试机制:超时后自动重新计时,直到达到 maxRetryCount 次;
  3. 事件触发:每次超时与最终失败都通过 UnityEvent 通知外部;
  4. 灵活配置:可在 Inspector 中设置超时时间、最大重试次数;
  5. 可复用组件:挂载即可使用,便于不同场景复用。

二、核心代码实现

以下是完整的 TimeoutDetector.cs 脚本代码:

using UnityEngine;
using UnityEngine.Events;

public class TimeoutDetector : MonoBehaviour
{
    [Tooltip("超时时间(秒)")]
    public float timeoutDuration = 5f;

    [Tooltip("最大重试次数")]
    public int maxRetryCount = 3;

    [Tooltip("每次超时时触发的事件")]
    public UnityEvent onTimeout;

    [Tooltip("达到最大重试次数时触发的事件")]
    public UnityEvent onMaxRetryReached;

    private int currentRetryCount = 0;
    private float timer = 0f;
    private bool isTiming = false;

    /// <summary>
    /// 开始计时检测
    /// </summary>
    public void StartDetection()
    {
        currentRetryCount = 0;
        RestartTimer();
    }

    /// <summary>
    /// 手动停止检测
    /// </summary>
    public void StopDetection()
    {
        isTiming = false;
        timer = 0f;
    }

    private void RestartTimer()
    {
        timer = 0f;
        isTiming = true;
    }

    private void Update()
    {
        if (!isTiming) return;

        timer += Time.deltaTime;

        if (timer >= timeoutDuration)
        {
            HandleTimeout();
        }
    }

    private void HandleTimeout()
    {
        isTiming = false;
        onTimeout?.Invoke();
        currentRetryCount++;

        if (currentRetryCount < maxRetryCount)
        {
            Debug.Log($"Timeout occurred. Retrying {currentRetryCount}/{maxRetryCount}...");
            RestartTimer(); // 再次启动超时检测
        }
        else
        {
            Debug.LogWarning("Max retry count reached.");
            onMaxRetryReached?.Invoke(); // 触发最终失败事件
        }
    }
}

三、组件使用方式

1. 添加组件到物体

你可以手动添加 TimeoutDetector 到任意 GameObject,或使用我们提供的编辑器菜单:

using UnityEditor;
using UnityEngine;

public class TimeoutTool : EditorWindow
{
    [MenuItem("Tools/Add TimeoutDetector Component")]
    public static void AddTimeoutDetector()
    {
        GameObject selected = Selection.activeGameObject;

        if (selected != null)
        {
            AddComponentIfMissing<TimeoutDetector>(selected);
        }
        else
        {
            Debug.LogError("请先选择一个 GameObject!");
        }
    }

    private static void AddComponentIfMissing<T>(GameObject obj) where T : Component
    {
        if (obj.GetComponent<T>() == null)
        {
            obj.AddComponent<T>();
            Debug.Log($"已添加组件:{typeof(T).Name}");
        }
        else
        {
            Debug.Log($"{typeof(T).Name} 已存在!");
        }
    }
}

菜单路径:Tools → Add TimeoutDetector Component


2. 场景中使用示例

public class TestTimeout : MonoBehaviour
{
    public TimeoutDetector detector;

    private void Start()
    {
        detector.onTimeout.AddListener(OnRetry);
        detector.onMaxRetryReached.AddListener(OnFail);

        detector.StartDetection(); // 启动检测
    }

    void OnRetry()
    {
        Debug.Log("超时一次,正在自动重试...");
    }

    void OnFail()
    {
        Debug.LogError("超时重试已达最大次数!");
    }
}

你可以通过 Unity Inspector 绑定事件,或通过代码注册监听器。


四、应用场景举例

1. 网络请求等待超时

// 模拟:5秒内必须收到响应,否则重试3次
timeoutDetector.onTimeout.AddListener(() => RetryRequest());
timeoutDetector.onMaxRetryReached.AddListener(() => ShowNetworkError());
timeoutDetector.StartDetection();

2. 等待玩家交互

timeoutDetector.timeoutDuration = 10f;
timeoutDetector.maxRetryCount = 1;

timeoutDetector.onTimeout.AddListener(() => {
    Debug.Log("玩家超时未响应,默认选择第一个选项");
    ApplyDefaultChoice();
});
timeoutDetector.StartDetection();

五、优化建议与扩展方向

为了让该组件更加健壮和灵活,你还可以做如下扩展:

扩展方向说明
✅ 支持暂停恢复Pause 状态下停止计时,恢复后继续
✅ 显示倒计时将 timer 显示到 UI
✅ 多状态触发比如触发每秒回调,用于动态显示
✅ 支持协程实现通过 IEnumerator 实现更清晰的控制流程

六、总结

本文从零实现了一个支持自动重试的 Unity 超时检测组件 TimeoutDetector,它具备以下优点:

  • 简洁易用,挂载即用;
  • 高度复用,可应用于网络、交互、AI 等场景;
  • 支持事件响应,方便扩展与组合逻辑;
  • 可自定义超时时间与重试次数,适配不同业务需求。

通过本示例,你不仅能掌握 Unity 中的组件开发技巧,还能理解如何用面向对象的思维编写可复用的逻辑工具。希望对你在项目中实现更智能、更稳定的逻辑控制有所帮助。


👉 新开专栏《VR 360°全景视频开发》,持续更新中,敬请关注!

【专栏预告】《VR 360°全景视频开发:从GoPro到Unity VR眼镜应用实战》

《VR 360°全景视频开发》将带你深入探索从GoPro拍摄到Unity眼镜端应用开发的全流程技术。专栏内容涵盖安卓原生VR播放器开发、Unity VR视频渲染与手势交互、360°全景视频制作与优化,以及高分辨率视频性能优化等实战技巧。敬请关注每周更新的技术分享!


相关文章:

  • AIP-231 批量方法:Get
  • 树莓派超全系列教程文档--(24)本地化设置、SSH及配置防火墙
  • 本地mock服务编写
  • 如何优雅地处理 API 版本控制?
  • 滚轮控制目标臂长度调整相机距离
  • CTF--shell
  • 自动驾驶第一性原理
  • java -jar 如何持久化运行
  • 华三IRF堆叠技术
  • Redis 5.0、6.0 和 7.0 版本的核心更新特性总结
  • flutter 打包mac程序 dmg教程
  • 【CUDA 】第3章 CUDA执行模型——3.5循环展开(1)
  • 探讨HMI(人机界面)设计原则,如何通过优秀的设计提升操作效率和用户体验
  • 第二十六:Map的基本原理
  • VM虚拟机安装及Ubuntu安装配置
  • Nacos操作指南
  • I/O进程(全)
  • RGBD惯性SLAM
  • 电弧光的危害有哪些?我们该如何应对?
  • 分布式热点网络
  • 巴基斯坦召开国家安全委员会紧急会议,应对印方连环举措
  • 嫦娥五号《月球样品借用协议》签约,2025中国航天公益形象大使公布
  • 全红婵、李宁亮相中国航天日论坛,体育和航天这一次紧密相连
  • 建行原副行长章更生被开除党籍:靠贷吃贷,大搞权钱交易
  • 世界地球日丨上海交响乐团牵手上海植物园,为“树”写交响曲
  • 洛阳白马寺内的狄仁杰墓挂上公示牌争论尘埃落定?瀍河区文旅局称已确认