diff --git a/Artists/Scripts/Factory/PlaybackService.cs b/Artists/Scripts/Factory/PlaybackService.cs index 4b0120f..26bbb88 100644 --- a/Artists/Scripts/Factory/PlaybackService.cs +++ b/Artists/Scripts/Factory/PlaybackService.cs @@ -20,7 +20,7 @@ public partial class PlaybackService : UXPanel [Export] private PackedScene template; [Export] private PackedScene labelTemplate; [Export] private DataPlayer dataPlayer; - + private CancellationTokenSource cancellationTokenSource; public PlaybackService() { BITApp.ServiceCollection.AddSingleton(this); @@ -28,11 +28,17 @@ public partial class PlaybackService : UXPanel public override void _Ready() { + cancellationTokenSource = new CancellationTokenSource(); OnExit(); } - + public override void _ExitTree() + { + cancellationTokenSource.Cancel(); + } public override void OnEntry() { + cancellationTokenSource.Token.ThrowIfCancellationRequested(); + var files = new DirectoryInfo(PathHelper.GetFolderPath("Demos", GetTree().CurrentScene.Name)) .GetFiles() @@ -62,8 +68,18 @@ public partial class PlaybackService : UXPanel await UniTask.SwitchToTaskPool(); var array = BITAssets.Read(x.FullName, "base64"); + + try + { + await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext, + cancellationTokenSource.Token); + } + catch (OperationCanceledException) + { + stopwatch.Stop(); + return; + } - await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext); stopwatch.Stop(); BIT4Log.Log($"已加载:{playableInfo.Name},耗时:{stopwatch.ElapsedMilliseconds}ms"); diff --git a/README.md b/README.md index a92a137..7e2e04f 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ * 快速替换预览设备的型号,例如将`KUKA.AGV`替换为`Intelli.AGV`\ #### 沙盒仿真(南岸信的可能性需求) * 基于`行为树`的顺序执行模式带来相对直观的设计 +* 基于`行为树`你可以直接设计生产流程,并支持通过http接入MES系统 * 行为树支持`Godot Editor`和`Runtime`模式,可以在编辑器或运行时编辑行为 * 基于行为树,你可以让`Entity`和`Signal`执行各种各样的操作,包括且不限于: * AGV移动到指定位置(可等待到达,或指定到达时间以及移动速度) @@ -271,8 +272,10 @@ public partial class RotationService:Node } public override _Process(double delta) { + //遍历所有包含RotationComponent的Entity foreach(var entity in EntitiesManager.Query()) { + //或者RotationComponent组件 if(entity.TryGetComponent(out var rotationComponent) { //获取该组件的角度 @@ -284,3 +287,113 @@ public partial class RotationService:Node } } ``` +#### 配置UI +首先你需要确保基于`Control`节点的`UXService`存在与`项目设置`中的`自动加载`中 +##### 创建UI面板 +接下来,创建一个新的类,继承自`IUXPanel`或者直接为UI面板的节点添加`UXPanel`就完成了UI的基本配置 + +`UXService`是基于消息队列的,你可以从多线程中添加队列 + +`UXService`支持`Return`,例如: +```csharp +//进入提示面板 +UXService.Entry(); +//返回到当前面板 +UXService.Return(); +``` +##### 如何进入某个UI面板? +在脚本中调用 +```csharp +UXService.Entry(this as IUXPanel); +``` +或者在信号中连接面板 +```csharp +UXPanel.Open(); +``` +#### 自动加载配置文件 +你需要手动在场景中添加节点`Exec`并配置好`json`文件的相对路径,例如:`Mods/EIPC/appsettings.json` +默认情况下,都会加载项目根目录下的`appsettings.json` +或者可以手动加载: +```csharp +DataParser.Set(json); +``` +所有基本的json类型都会加载到全局变量`Data`中 +#### 获取和监听配置文件 +```csharp +//获取配置(全局变量) +Data.Get(string:key); +//获取单个配置 +Data.Get(); +//监听变量 +Data.AddListener("MyEvent",MyCallback); +void MyCallaback(T value); +//设置变量 +Data.Invoke("MyEvent",value); +``` +#### 基于UniTask的异步与多线程使用方式 +原理就是在处理数据时切换到线程池,并在处理完成后返回主线程 +这里涉及到 +```csharp +//处理任务之前的准备,例如 + +//创建计时器,计算任务耗时 +Stopwatch stopwatch = new(); +stopwatch.Start(); + +//切换到任务池(默认为线程池) +await UniTask.SwitchToTaskPool(); + +//在这里处理你的复杂任务,例如: +DiggingBitcoin(); +CrackWifiPassword(); +RmRf(); + +//在完成任务后,切换回主线程 +try +{ + //切换回主线程的同时,应该添加CancellationToken + await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext, + cancellationTokenSource.Token); +} +catch (OperationCanceledException) +{ + //任务取消后应该怎么处理,比如回滚数据 + return; +} + +//完成任务后,打印出任务耗时时间 +Console.WriteLine($"该任务耗时:{stopwatch.ElapsedMilliseconds}ms"); +``` +##### 怎么取消任务 +在创建await任务时,添加CancellationToken + +通常CancellationToken是这么构成的 +```csharp +//声明一个CancellationTokenSource +private CancellationTokenSource cancellationTokenSource; +public override void _Ready() +{ + //创建新的CancellationTokenSource + cancellationTokenSource = new CancellationTokenSource(); +} +public override void _ExitTree() +{ + //取消任务 + cancellationTokenSource.Cancel(); +} +public override void _Process() +{ + //如果任务已取消,抛出任务取消的异常 + cancellationTokenSource.Token.ThrowIfCancellationRequested(); + + //用try catch捕获取消异常 + try + { + //等待某个任务,并添加CancellationToken + await SomeAsync(cancellationTokenSource.Token); + }catch(OperationCanceledException) + { + //任务已取消,你需要做些什么,比如回滚数据 + } +} +``` \ No newline at end of file