如何从按钮点击事件调用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
相关产品推荐
相关产品推荐

