Skip to content
This repository has been archived by the owner on Aug 9, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2 from edanoue/v2.1.1
Browse files Browse the repository at this point in the history
V2.1.1
  • Loading branch information
minami110 committed Mar 31, 2023
2 parents a03545b + ea2d07c commit 0e17b4f
Show file tree
Hide file tree
Showing 49 changed files with 984 additions and 340 deletions.
43 changes: 23 additions & 20 deletions Runtime/HybridGraph/BehaviourTree/Actions/Action.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,40 @@ namespace Edanoue.HybridGraph
{
public static class ActionExtensions
{
private const string _DEFAULT_NAME = "Action";

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <param name="action"></param>
/// <returns></returns>
public static IActionNode Action(this ICompositePort self, Func<bool> action)
{
return self.Action(action, "Action");
return self.Action(action, _DEFAULT_NAME);
}

public static IActionNode Action(this ICompositePort self, Func<bool> action, string name)
{
var node = new BtActionNodeAction(action, name);
self.AddNode(node);
var node = new BtActionNodeAction(action);
self.AddNode(node, name);
return node;
}

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <param name="action"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IActionNode Action<T>(this ICompositePort self, Func<T, bool> action)
{
return self.Action(action, "Action");
return self.Action(action, _DEFAULT_NAME);
}

public static IActionNode Action<T>(this ICompositePort self, Func<T, bool> action, string name)
{
var node = new BtActionNodeAction<T>(action, name);
self.AddNode(node);
var node = new BtActionNodeAction<T>(action);
self.AddNode(node, name);
return node;
}
}
Expand All @@ -38,39 +51,29 @@ internal sealed class BtActionNodeAction : BtActionNode
{
private readonly Func<bool> _action;

internal BtActionNodeAction(Func<bool> action, string name) : base(name)
internal BtActionNodeAction(Func<bool> action)
{
_action = action;
}

internal override UniTask<BtNodeResult> ExecuteAsync(CancellationToken token)
{
if (_action.Invoke())
{
return UniTask.FromResult(BtNodeResult.Succeeded);
}

return UniTask.FromResult(BtNodeResult.Failed);
return UniTask.FromResult(_action.Invoke() ? BtNodeResult.Succeeded : BtNodeResult.Failed);
}
}

internal sealed class BtActionNodeAction<T> : BtActionNode
{
private readonly Func<T, bool> _action;

internal BtActionNodeAction(Func<T, bool> action, string name) : base(name)
internal BtActionNodeAction(Func<T, bool> action)
{
_action = action;
}

internal override UniTask<BtNodeResult> ExecuteAsync(CancellationToken token)
{
if (_action.Invoke((T)Blackboard))
{
return UniTask.FromResult(BtNodeResult.Succeeded);
}

return UniTask.FromResult(BtNodeResult.Failed);
return UniTask.FromResult(_action.Invoke((T)Blackboard) ? BtNodeResult.Succeeded : BtNodeResult.Failed);
}
}
}
23 changes: 19 additions & 4 deletions Runtime/HybridGraph/BehaviourTree/Actions/ActionAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,32 @@ namespace Edanoue.HybridGraph
{
public static class ActionAsyncExtensions
{
private const string _DEFAULT_NAME = "ActionAsync";

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <param name="asyncAction"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IActionNode ActionAsync<T>(this ICompositePort self,
Func<T, CancellationToken, UniTask<bool>> asyncAction)
{
return self.ActionAsync(asyncAction, "ActionAsync");
return self.ActionAsync(asyncAction, _DEFAULT_NAME);
}

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <param name="asyncAction"></param>
/// <param name="name"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IActionNode ActionAsync<T>(this ICompositePort self,
Func<T, CancellationToken, UniTask<bool>> asyncAction, string name)
{
var node = new BtActionNodeActionAsync<T>(asyncAction, name);
self.AddNode(node);
var node = new BtActionNodeActionAsync<T>(asyncAction);
self.AddNode(node, name);
return node;
}
}
Expand All @@ -28,7 +43,7 @@ internal sealed class BtActionNodeActionAsync<T> : BtActionNode
{
private readonly Func<T, CancellationToken, UniTask<bool>> _action;

public BtActionNodeActionAsync(Func<T, CancellationToken, UniTask<bool>> action, string name) : base(name)
public BtActionNodeActionAsync(Func<T, CancellationToken, UniTask<bool>> action)
{
_action = action;
}
Expand Down
34 changes: 34 additions & 0 deletions Runtime/HybridGraph/BehaviourTree/Actions/BehaviourTree.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright Edanoue, Inc. All Rights Reserved.

#nullable enable
namespace Edanoue.HybridGraph
{
public static class BehaviourTreeExtensions
{
private const string _DEFAULT_NAME = "BehaviourTree";

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static IActionNode BehaviourTree<T>(this ICompositePort self)
where T : BehaviourTreeBase, new()
{
return self.BehaviourTree<T>(_DEFAULT_NAME);
}

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <param name="name"></param>
/// <returns></returns>
public static IActionNode BehaviourTree<T>(this ICompositePort self, string name)
where T : BehaviourTreeBase, new()
{
var node = new T();
self.AddNode(node, name);
node.SetupBehaviours();
return node;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 11 additions & 4 deletions Runtime/HybridGraph/BehaviourTree/Actions/Wait.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ namespace Edanoue.HybridGraph
{
public static class WaitExtensions
{
private const string _DEFAULT_NAME = "Wait";

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <param name="timeSpan"></param>
/// <returns></returns>
public static IActionNode Wait(this ICompositePort self, TimeSpan timeSpan)
{
return self.Wait(timeSpan, "Wait");
return self.Wait(timeSpan, _DEFAULT_NAME);
}

public static IActionNode Wait(this ICompositePort self, TimeSpan timeSpan, string name)
{
var node = new BtActionNodeWait(timeSpan, name);
self.AddNode(node);
var node = new BtActionNodeWait(timeSpan);
self.AddNode(node, name);
return node;
}
}
Expand All @@ -26,7 +33,7 @@ internal sealed class BtActionNodeWait : BtActionNode
{
private readonly TimeSpan _timeSpan;

internal BtActionNodeWait(TimeSpan timeSpan, string name) : base(name)
internal BtActionNodeWait(TimeSpan timeSpan)
{
_timeSpan = timeSpan;
}
Expand Down
94 changes: 70 additions & 24 deletions Runtime/HybridGraph/BehaviourTree/BehaviourTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,115 @@

#nullable enable
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;

namespace Edanoue.HybridGraph
{
public abstract class BehaviourTree<TBlackboard> : IGraphBox
public abstract class BehaviourTreeBase : BtActionNode
{
private readonly BtRootNode _rootNode = new();
private IGraphBox? _parent;
protected TBlackboard Blackboard = default!;
private protected readonly BtRootNode RootNode = new();

public void Dispose()
internal sealed override async UniTask<BtNodeResult> ExecuteAsync(CancellationToken token)
{
throw new NotImplementedException();
return await RootNode.ExecuteAsync(token);
}

IGraphNode IGraphItem.RootNode => _rootNode;
internal void SetupBehaviours()
{
RootNode.SetBlackboard(Blackboard);
OnSetupBehaviours(RootNode);
}

/// <summary>
/// </summary>
/// <param name="root"></param>
protected abstract void OnSetupBehaviours(IRootNode root);
}

public abstract class BehaviourTree<TBlackboard> : BehaviourTreeBase, IGraphNode, IGraphEntryNode
{
/// <summary>
/// 内部用のTransition Table
/// 遷移先を辞書形式で保存している
/// </summary>
// ReSharper disable once InconsistentNaming
private readonly Dictionary<int, IGraphNode> _transitionTable = new();

void IGraphItem.Initialize(object blackboard, IGraphBox? parent)
IGraphNode IGraphEntryNode.Run(object blackboard)
{
if (_rootNode.ChildCount != 0)
if (RootNode.ChildCount != 0)
{
throw new InvalidOperationException("Behaviour tree is already started.");
}

Blackboard = (TBlackboard)blackboard ?? throw new ArgumentNullException(nameof(blackboard));
_parent = parent;
((IGraphItem)_rootNode).Initialize(blackboard, this);
OnSetupBehaviours(_rootNode);
Blackboard = blackboard;
SetupBehaviours();

// Setup validation check
if (_rootNode.ChildCount != 1)
if (RootNode.ChildCount != 1)
{
throw new InvalidOperationException("Root node must have one child.");
}

return this;
}

public void Dispose()
{
RootNode.Dispose();
}

void IGraphItem.Connect(int trigger, IGraphItem nextNode)
{
throw new NotImplementedException();
if (_transitionTable.ContainsKey(trigger))
{
throw new ArgumentException($"Already registered trigger: {trigger}");
}

_transitionTable.Add(trigger, nextNode.GetEntryNode());
}

void IGraphItem.OnInitializedInternal(object blackboard, IGraphBox parent)
{
if (RootNode.ChildCount != 0)
{
throw new InvalidOperationException("Behaviour tree is already started.");
}

Blackboard = blackboard;
SetupBehaviours();

// Setup validation check
if (RootNode.ChildCount != 1)
{
throw new InvalidOperationException("Root node must have one child.");
}
}

void IGraphItem.OnEnterInternal()
{
throw new NotImplementedException();
RootNode.OnEnter();
}

void IGraphItem.OnUpdateInternal()
{
throw new NotImplementedException();
}

void IGraphItem.OnExitInternal(IGraphItem nextNode)
{
throw new NotImplementedException();
RootNode.OnExit();
}

bool IGraphBox.IsDescendantNode(IGraphItem node)
IGraphNode IGraphItem.GetEntryNode()
{
throw new NotImplementedException();
return this;
}

/// <summary>
/// </summary>
/// <param name="root"></param>
protected abstract void OnSetupBehaviours(IRootNode root);
bool IGraphNode.TryGetNextNode(int trigger, out IGraphNode nextNode)
{
return _transitionTable.TryGetValue(trigger, out nextNode);
}
}
}
21 changes: 14 additions & 7 deletions Runtime/HybridGraph/BehaviourTree/Composites/Selector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,26 @@ namespace Edanoue.HybridGraph
{
public static class SelectorExtensions
{
private const string _DEFAULT_NAME = "Selector";

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static ICompositeNode Selector(this ICompositePort self)
{
return self.Selector("Selector");
return self.Selector(_DEFAULT_NAME);
}

/// <summary>
/// </summary>
/// <param name="self"></param>
/// <param name="name"></param>
/// <returns></returns>
public static ICompositeNode Selector(this ICompositePort self, string name)
{
var node = new BtCompositeNodeSelector(name);
self.AddNode(node);
var node = new BtCompositeNodeSelector();
self.AddNode(node, name);
return node;
}
}
Expand All @@ -22,10 +33,6 @@ public static ICompositeNode Selector(this ICompositePort self, string name)
/// </summary>
internal sealed class BtCompositeNodeSelector : BtCompositeNode
{
public BtCompositeNodeSelector(string name) : base(name)
{
}

protected override int GetNextChildIndex(int prevChild, in BtNodeResult lastResult)
{
var nextChild = BtSpecialChild.RETURN_TO_PARENT;
Expand Down
Loading

0 comments on commit 0e17b4f

Please sign in to comment.