From ba79f4e1340c924cb2c9174c673cc7ac30714c6e Mon Sep 17 00:00:00 2001 From: Dmitry Baltin Date: Fri, 5 Sep 2025 22:18:07 +0200 Subject: [PATCH 1/3] feat: removed CancellationToken from all the arguments to make the BT syntax more compact --- Runtime/UnitaskFbtNodes.cs | 118 ++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 61 deletions(-) diff --git a/Runtime/UnitaskFbtNodes.cs b/Runtime/UnitaskFbtNodes.cs index 820d140..e6a4e2b 100644 --- a/Runtime/UnitaskFbtNodes.cs +++ b/Runtime/UnitaskFbtNodes.cs @@ -24,9 +24,8 @@ public static class UnitaskFbtNodes [MethodImpl(MethodImplOptions.AggressiveInlining)] public static async UniTask Inverter( this T board, - CancellationToken ct, - Func> func) - => !await func.Invoke(board, ct); + Func> func) + => !await func.Invoke(board); /// /// Execute the given func delegate if the given condition is true @@ -39,10 +38,9 @@ public static async UniTask Inverter( [MethodImpl(MethodImplOptions.AggressiveInlining)] public static async UniTask If( this T board, - CancellationToken ct, Func condition, - Func> func) - => condition.Invoke(board) && await func.Invoke(board, ct); + Func> func) + => condition.Invoke(board) && await func.Invoke(board); /// /// Classic selector node @@ -59,24 +57,24 @@ public static async UniTask If( /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async UniTask Selector(this T board, CancellationToken token, - Func> f1, - Func> f2, - Func> f3 = null, - Func> f4 = null, - Func> f5 = null, - Func> f6 = null, - Func> f7 = null, - Func> f8 = null) + public static async UniTask Selector(this T board, + Func> f1, + Func> f2, + Func> f3 = null, + Func> f4 = null, + Func> f5 = null, + Func> f6 = null, + Func> f7 = null, + Func> f8 = null) { - var s = f1 is not null && await f1.Invoke(board, token); if(s) return true; - s = f2 is not null && await f2.Invoke(board, token); if(s) return true; - s = f3 is not null && await f3.Invoke(board, token); if(s) return true; - s = f4 is not null && await f4.Invoke(board, token); if(s) return true; - s = f5 is not null && await f5.Invoke(board, token); if(s) return true; - s = f6 is not null && await f6.Invoke(board, token); if(s) return true; - s = f7 is not null && await f7.Invoke(board, token); if(s) return true; - s = f8 is not null && await f8.Invoke(board, token); if(s) return true; + var s = f1 is not null && await f1.Invoke(board); if(s) return true; + s = f2 is not null && await f2.Invoke(board); if(s) return true; + s = f3 is not null && await f3.Invoke(board); if(s) return true; + s = f4 is not null && await f4.Invoke(board); if(s) return true; + s = f5 is not null && await f5.Invoke(board); if(s) return true; + s = f6 is not null && await f6.Invoke(board); if(s) return true; + s = f7 is not null && await f7.Invoke(board); if(s) return true; + s = f8 is not null && await f8.Invoke(board); if(s) return true; return false; } @@ -95,24 +93,24 @@ public static async UniTask Selector(this T board, CancellationToken to /// Optional delegate receiving T and returning Status /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async UniTask Sequencer(this T board, CancellationToken token, - Func> f1, - Func> f2, - Func> f3 = null, - Func> f4 = null, - Func> f5 = null, - Func> f6 = null, - Func> f7 = null, - Func> f8 = null) + public static async UniTask Sequencer(this T board, + Func> f1, + Func> f2, + Func> f3 = null, + Func> f4 = null, + Func> f5 = null, + Func> f6 = null, + Func> f7 = null, + Func> f8 = null) { - var s = f1 is not null && await f1.Invoke(board, token); if(!s) return false; - s = f2 is not null && await f2.Invoke(board, token); if(!s) return false; - s = f3 is not null && await f3.Invoke(board, token); if(!s) return false; - s = f4 is not null && await f4.Invoke(board, token); if(!s) return false; - s = f5 is not null && await f5.Invoke(board, token); if(!s) return false; - s = f6 is not null && await f6.Invoke(board, token); if(!s) return false; - s = f7 is not null && await f7.Invoke(board, token); if(!s) return false; - s = f8 is not null && await f8.Invoke(board, token); if(!s) return false; + var s = f1 is not null && await f1.Invoke(board); if(!s) return false; + s = f2 is not null && await f2.Invoke(board); if(!s) return false; + s = f3 is not null && await f3.Invoke(board); if(!s) return false; + s = f4 is not null && await f4.Invoke(board); if(!s) return false; + s = f5 is not null && await f5.Invoke(board); if(!s) return false; + s = f6 is not null && await f6.Invoke(board); if(!s) return false; + s = f7 is not null && await f7.Invoke(board); if(!s) return false; + s = f8 is not null && await f8.Invoke(board); if(!s) return false; return true; } @@ -132,13 +130,12 @@ public static async UniTask Sequencer(this T board, CancellationToken t [MethodImpl(MethodImplOptions.AggressiveInlining)] public static async UniTask ConditionalInverter( this T board, - CancellationToken token, Func condition, - Func> func, - Func> elseFunc = null) + Func> func, + Func> elseFunc = null) => condition.Invoke(board) - ? await board.Inverter(token, func) - : elseFunc != null && await board.Inverter(token, elseFunc); + ? await board.Inverter(func) + : elseFunc != null && await board.Inverter(elseFunc); /// /// Check condition before Selector @@ -156,15 +153,14 @@ public static async UniTask ConditionalInverter( [MethodImpl(MethodImplOptions.AggressiveInlining)] public static async UniTask ConditionalSelector( this T board, - CancellationToken token, Func condition, - Func> f1, - Func> f2, - Func> f3 = null, - Func> f4 = null, - Func> f5 = null, - Func> f6 = null) - => condition.Invoke(board) && await board.Selector(token, f1, f2, f3, f4, f5, f6); + Func> f1, + Func> f2, + Func> f3 = null, + Func> f4 = null, + Func> f5 = null, + Func> f6 = null) + => condition.Invoke(board) && await board.Selector(f1, f2, f3, f4, f5, f6); /// /// Check condition before Sequencer @@ -179,14 +175,14 @@ public static async UniTask ConditionalSelector( /// Optional delegate receiving T and returning Status /// If the condition is false return Failure. Else return the result of Sequencer [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async UniTask ConditionalSequencer(this T board, CancellationToken token, + public static async UniTask IfSequencer(this T board, Func condition, - Func> f1, - Func> f2, - Func> f3 = null, - Func> f4 = null, - Func> f5 = null, - Func> f6 = null) - => condition.Invoke(board) && await board.Sequencer(token, f1, f2, f3, f4, f5, f6); + Func> f1, + Func> f2, + Func> f3 = null, + Func> f4 = null, + Func> f5 = null, + Func> f6 = null) + => condition.Invoke(board) && await board.Sequencer(f1, f2, f3, f4, f5, f6); } } \ No newline at end of file From 5164bb54ed9dde1c314f3e19118e24a43385fe82 Mon Sep 17 00:00:00 2001 From: Dmitry Baltin Date: Sat, 6 Sep 2025 10:46:50 +0200 Subject: [PATCH 2/3] feat: uFBT definition is simplified - namespace renamed UnitaskFBT -> UFBT - removed extra Inverter node - names of conditional nodes ar shortened --- Runtime/UnitaskFbtNodes.cs | 73 ++++++++++++-------------------------- 1 file changed, 22 insertions(+), 51 deletions(-) diff --git a/Runtime/UnitaskFbtNodes.cs b/Runtime/UnitaskFbtNodes.cs index e6a4e2b..0edf00d 100644 --- a/Runtime/UnitaskFbtNodes.cs +++ b/Runtime/UnitaskFbtNodes.cs @@ -3,7 +3,7 @@ using System.Threading; using Cysharp.Threading.Tasks; -namespace Baltin.UnitaskFBT +namespace Baltin.UFBT { /// /// Async Functional Behavior Tree pattern @@ -15,18 +15,6 @@ namespace Baltin.UnitaskFBT /// Type of 'blackboard' that represents the controlled object. public static class UnitaskFbtNodes { - /// - /// Classic inverter node - /// - /// Blackboard object - /// Delegate receiving T and returning Status - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async UniTask Inverter( - this T board, - Func> func) - => !await func.Invoke(board); - /// /// Execute the given func delegate if the given condition is true /// @@ -40,7 +28,7 @@ public static async UniTask If( this T board, Func condition, Func> func) - => condition.Invoke(board) && await func.Invoke(board); + => condition(board) && await func(board); /// /// Classic selector node @@ -67,18 +55,19 @@ public static async UniTask Selector(this T board, Func> f7 = null, Func> f8 = null) { - var s = f1 is not null && await f1.Invoke(board); if(s) return true; - s = f2 is not null && await f2.Invoke(board); if(s) return true; - s = f3 is not null && await f3.Invoke(board); if(s) return true; - s = f4 is not null && await f4.Invoke(board); if(s) return true; - s = f5 is not null && await f5.Invoke(board); if(s) return true; - s = f6 is not null && await f6.Invoke(board); if(s) return true; - s = f7 is not null && await f7.Invoke(board); if(s) return true; - s = f8 is not null && await f8.Invoke(board); if(s) return true; + var s = await f1(board); if(s) return true; + s = await f2(board); if(s) return true; + s = f3 is not null && await f3(board); if(s) return true; + s = f4 is not null && await f4(board); if(s) return true; + s = f5 is not null && await f5(board); if(s) return true; + s = f6 is not null && await f6(board); if(s) return true; + s = f7 is not null && await f7(board); if(s) return true; + s = f8 is not null && await f8(board); if(s) return true; return false; } + // ReSharper disable Unity.PerformanceAnalysis /// /// Classic sequencer node /// @@ -103,14 +92,14 @@ public static async UniTask Sequencer(this T board, Func> f7 = null, Func> f8 = null) { - var s = f1 is not null && await f1.Invoke(board); if(!s) return false; - s = f2 is not null && await f2.Invoke(board); if(!s) return false; - s = f3 is not null && await f3.Invoke(board); if(!s) return false; - s = f4 is not null && await f4.Invoke(board); if(!s) return false; - s = f5 is not null && await f5.Invoke(board); if(!s) return false; - s = f6 is not null && await f6.Invoke(board); if(!s) return false; - s = f7 is not null && await f7.Invoke(board); if(!s) return false; - s = f8 is not null && await f8.Invoke(board); if(!s) return false; + var s = await f1(board); if(!s) return false; + s = await f2(board); if(!s) return false; + s = f3 is not null && await f3(board); if(!s) return false; + s = f4 is not null && await f4(board); if(!s) return false; + s = f5 is not null && await f5(board); if(!s) return false; + s = f6 is not null && await f6(board); if(!s) return false; + s = f7 is not null && await f7(board); if(!s) return false; + s = f8 is not null && await f8(board); if(!s) return false; return true; } @@ -119,24 +108,6 @@ public static async UniTask Sequencer(this T board, //Every conditional node can be replaced by two nodes the first of them is an Action node containing the condition and wrapping the second mains node //But usually is more convenient to use one conditional node instead - /// - /// Check condition, execute given action and then return its inverted result - /// - /// Blackboard object - /// Condition given as a delegate returning bool - /// Action returning Status - /// - /// If the condition is false return Failure. Else return inverted value of the func - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async UniTask ConditionalInverter( - this T board, - Func condition, - Func> func, - Func> elseFunc = null) - => condition.Invoke(board) - ? await board.Inverter(func) - : elseFunc != null && await board.Inverter(elseFunc); - /// /// Check condition before Selector /// Returns Failure if the condition is false @@ -151,7 +122,7 @@ public static async UniTask ConditionalInverter( /// Optional delegate receiving T and returning Status /// If the condition is false return Failure. Else return the result of Selector [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async UniTask ConditionalSelector( + public static async UniTask IfSelector( this T board, Func condition, Func> f1, @@ -160,7 +131,7 @@ public static async UniTask ConditionalSelector( Func> f4 = null, Func> f5 = null, Func> f6 = null) - => condition.Invoke(board) && await board.Selector(f1, f2, f3, f4, f5, f6); + => condition(board) && await board.Selector(f1, f2, f3, f4, f5, f6); /// /// Check condition before Sequencer @@ -183,6 +154,6 @@ public static async UniTask IfSequencer(this T board, Func> f4 = null, Func> f5 = null, Func> f6 = null) - => condition.Invoke(board) && await board.Sequencer(f1, f2, f3, f4, f5, f6); + => condition(board) && await board.Sequencer(f1, f2, f3, f4, f5, f6); } } \ No newline at end of file From c0477a82718d2c9484f01fad21f0f34ef58ccb7c Mon Sep 17 00:00:00 2001 From: Dmitry Baltin Date: Sat, 6 Sep 2025 10:48:37 +0200 Subject: [PATCH 3/3] chore: version incremented (incompatible with previous version) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c27ed7..f5798dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.baltin.ufbt", - "version": "0.5.4", + "version": "0.6.0", "displayName": "UniTaskFBT", "description": "Async Functional Behavior Tree implementation based on UniTask", "unity": "2021.2",