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

如何从按钮点击事件调用Unity异步MonoBehaviour类的启动逻辑?

问题解决方法

首先要指出你原代码里的致命问题:Start方法中的while (!res)会完全阻塞Unity主线程,导致异步方法的await回调永远无法执行,整个游戏会直接卡死,必须先删掉这个循环。

接下来是从外部类调用PipelineExample逻辑的具体步骤:

1. 修改PipelineExample类

把启动逻辑改成外部可调用的公共方法,同时修复主线程阻塞问题:

using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

public class PipelineExample : MonoBehaviour
{
    private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

    // Unity生命周期方法,这里不再自动启动逻辑,留空或按需使用
    void Start()
    {
    }

    // 改成public,让外部类可以直接调用
    public async void StartPipeline()
    {
        IModel fbxModel = new FbxModel();
        Pipeline<IModel> pipeline = new Pipeline<IModel>();
        IAction<IModel> pipelineStep = new GenericPipelineStep<IModel>();

        pipeline.AddPipeLineStep(pipelineStep);

        try
        {
            bool res = await pipeline.Execute(fbxModel, cancellationTokenSource.Token);
            Debug.Log("Result of pipeline: " + res); // Unity用Debug.Log替代Console,才能在编辑器控制台看到输出
        }
        catch (OperationCanceledException)
        {
            Debug.Log("Canceled successfully!");
        }
    }

    // 可选:添加公共取消方法,方便外部终止管道
    public void CancelPipeline()
    {
        cancellationTokenSource.Cancel();
    }

    void Update()
    {
    }
}

2. 在按钮点击类中实现调用逻辑

因为PipelineExample继承自MonoBehaviour,不能直接new实例,必须依附在GameObject上,有两种方式获取实例:

方式一:Inspector面板拖拽赋值(推荐,性能更高)

using UnityEngine;
using UnityEngine.UIElements;

public class UIManager : MonoBehaviour
{
    // 在Inspector面板把场景中的PipelineExample对象拖到这里
    [SerializeField] private PipelineExample _pipelineExample;

    private void OnStartButtonClicked(MouseUpEvent evt)
    {
        // 检查实例是否有效
        if (_pipelineExample == null)
        {
            Debug.LogError("PipelineExample实例未赋值!");
            return;
        }

        // 调用启动方法
        _pipelineExample.StartPipeline();
    }
}

方式二:动态查找或创建实例

如果场景中没有提前放置PipelineExample对象,可以动态查找或创建:

using UnityEngine;
using UnityEngine.UIElements;

public class UIManager : MonoBehaviour
{
    private void OnStartButtonClicked(MouseUpEvent evt)
    {
        // 查找场景中已存在的PipelineExample实例
        PipelineExample pipelineExample = FindObjectOfType<PipelineExample>();

        // 如果找不到,动态创建一个GameObject并挂载组件
        if (pipelineExample == null)
        {
            GameObject pipelineObj = new GameObject("PipelineExample");
            pipelineExample = pipelineObj.AddComponent<PipelineExample>();
        }

        // 调用启动方法
        pipelineExample.StartPipeline();
    }
}

关键注意事项

  • 永远不要在Unity主线程中写无限循环(比如while (!res)),会导致游戏无响应,异步回调也无法执行。
  • MonoBehaviour子类不能直接用new实例化,必须通过AddComponent添加到GameObject上,或获取场景中已存在的实例。
  • Unity中调试输出用Debug.Log,而非Console.Write,后者的内容不会显示在Unity编辑器的控制台里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 02:40:33