在unity中实现自定义时间后,激活指定组件

YunSun 发布于 2 天前 15 次阅读


常用方法有四种

  • 协程 (Coroutine)
  • Invoke 方法
  • Update 计时
  • DoTween (插件)

基础示例:延时2秒后激活游戏对象

方法一:使用协程 (Coroutine)

协程是Unity中实现延时逻辑的推荐方法,因为它清晰、灵活且易于控制。你可以让游戏对象在指定的时间后激活。

using System.Collections;
using UnityEngine;

public class DelayActivation : MonoBehaviour
{
    public GameObject targetObject; // 要激活的目标对象

    void Start()
    {
        // 在Start中启动协程,2秒后激活目标对象
        StartCoroutine(ActivateAfterDelay(2f));
    }

    IEnumerator ActivateAfterDelay(float delay)
    {
        // 等待delay秒
        yield return new WaitForSeconds(delay);
        // 时间到,激活目标对象
        if (targetObject != null)
            targetObject.SetActive(true);
    }
}

如果希望在按下特定按键时启动延时,可以将StartCoroutine放入响应按键的代码中。

方法二:使用 Invoke 方法

InvokeMonoBehaviour自带的方法,使用非常简单,特别适合快速实现一次性的延时调用。它的原理是在指定时间后调用一个方法

using UnityEngine;

public class InvokeActivation : MonoBehaviour
{
    public GameObject targetObject; // 要激活的目标对象

    void Start()
    {
        // 在Start中调用Invoke,2秒后执行ActivateObject方法
        Invoke("ActivateObject", 2f);
    }

    void ActivateObject()
    {
        if (targetObject != null)
            targetObject.SetActive(true);
    }
}

Invoke也支持周期性调用,使用InvokeRepeating("ActivateObject", 2f, 1f)即可实现首次延迟2秒,之后每1秒调用一次。

方法三:使用 Update 函数计时

这是最基础的手动计时方式,通过在Update函数中累加Time.deltaTime来实现。它的控制精度最高。

using UnityEngine;

public class UpdateTimerActivation : MonoBehaviour
{
    public GameObject targetObject; // 要激活的目标对象
    public float delayTime = 2f;    // 延迟时间,单位为秒
    
    private float timer = 0f;
    private bool isActivated = false;

    void Update()
    {
        // 如果还没激活,开始计时
        if (!isActivated)
        {
            // 累加每帧的时间
            timer += Time.deltaTime;
            // 当累加时间达到或超过延迟时间时
            if (timer >= delayTime)
            {
                if (targetObject != null)
                    targetObject.SetActive(true);
                isActivated = true; // 标记为已激活,防止重复执行
            }
        }
    }
}

方法四:使用 DoTween 插件

如果你的项目中已经使用了DoTween插件,它的Sequence可以实现延时回调,而且默认不受Time.timeScale影响

using DG.Tweening;
using UnityEngine;

public class DoTweenActivation : MonoBehaviour
{
    public GameObject targetObject; // 要激活的目标对象

    void Start()
    {
        // 创建一个动画序列
        Sequence mySequence = DOTween.Sequence();
        // 先插入2秒的等待
        mySequence.AppendInterval(2f);
        // 等待结束后,回调一个函数
        mySequence.AppendCallback(() => {
            if (targetObject != null)
                targetObject.SetActive(true);
        });
    }
}

延迟时间可以直接在代码中更改,或者将延迟时间设置为一个 public 变量,在 Unity 编辑器的 Inspector 窗口中就能随意调整。

public class InvokeActivationWithConfig : MonoBehaviour
{
    public GameObject targetObject;   // 要激活的目标对象
    public float delayTime = 2f;      // 可在 Inspector 中自定义,单位:秒

    void Start()
    {
        // 调用 Invoke,延迟 delayTime 秒后执行激活
        Invoke("ActivateObject", delayTime);
    }

    void ActivateObject()
    {
        if (targetObject != null)
            targetObject.SetActive(true);
    }
}

或者是通过 UI 输入框(InputField)让玩家实时输入时间。

适合需要运行时动态指定延迟时间的场景(比如玩家输入一个数字,点击按钮后开始计时)。

步骤:

  • 在 Canvas 下创建一个 InputField(输入框)和一个 Button(按钮)。
  • 创建如下脚本,挂载到任意 GameObject 上。
  • 在 Inspector 中绑定 UI 组件和要激活的目标对象。
using UnityEngine;
using UnityEngine.UI;

public class InvokeWithUserInput : MonoBehaviour
{
    public GameObject targetObject;       // 要激活的目标对象
    public InputField timeInputField;     // UI 输入框(让玩家输入秒数)
    public Button activateButton;         // 触发计时的按钮

    void Start()
    {
        // 给按钮绑定点击事件
        activateButton.onClick.AddListener(OnButtonClick);
    }

    void OnButtonClick()
    {
        // 尝试解析输入框中的文字为 float
        if (float.TryParse(timeInputField.text, out float userDelay))
        {
            // 确保延迟时间不为负数
            userDelay = Mathf.Max(0, userDelay);
            
            // 取消之前的 Invoke(避免重复计时)
            CancelInvoke();
            
            // 重新开始计时
            Invoke("ActivateObject", userDelay);
            
            Debug.Log($"将在 {userDelay} 秒后激活 {targetObject.name}");
        }
        else
        {
            Debug.LogWarning("输入的时间无效,请输入数字,例如 2.5");
        }
    }

    void ActivateObject()
    {
        if (targetObject != null)
            targetObject.SetActive(true);
        Debug.Log($"{targetObject.name} 已激活");
    }
}
此作者没有提供个人介绍。
最后更新于 2026-04-10