diff --git a/Runtime/Engine/Code/AI.meta b/Runtime/Engine/Code/AI.meta new file mode 100644 index 0000000..ab138b4 --- /dev/null +++ b/Runtime/Engine/Code/AI.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fd68bda548e04d3a9bff890d2c262d44 +timeCreated: 1760017432 \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/BehaviourNode.cs b/Runtime/Engine/Code/AI/BehaviourNode.cs new file mode 100644 index 0000000..2054a31 --- /dev/null +++ b/Runtime/Engine/Code/AI/BehaviourNode.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; + +namespace RebootKit.Engine.AI { + public class BehaviourNode { + public enum Status { + Success, + Failure, + Running + } + + public readonly string Name; + + public readonly List Children = new List(); + + protected int m_CurrentChild; + + public BehaviourNode(string name) { + Name = name; + } + + public void AddChild(BehaviourNode child) { + Children.Add(child); + } + + public virtual Status Process(float dt) { + return Children[m_CurrentChild].Process(dt); + } + + public virtual void Reset() { + m_CurrentChild = 0; + + for (int i = 0; i < Children.Count; i++) { + Children[i].Reset(); + } + } + } + +} \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/BehaviourNode.cs.meta b/Runtime/Engine/Code/AI/BehaviourNode.cs.meta new file mode 100644 index 0000000..00c4b46 --- /dev/null +++ b/Runtime/Engine/Code/AI/BehaviourNode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c1f6ae41eb91433f91a170b11173e7c3 +timeCreated: 1760018098 \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/BehaviourTree.cs b/Runtime/Engine/Code/AI/BehaviourTree.cs new file mode 100644 index 0000000..6a3e338 --- /dev/null +++ b/Runtime/Engine/Code/AI/BehaviourTree.cs @@ -0,0 +1,19 @@ +namespace RebootKit.Engine.AI { + public class BehaviourTree : BehaviourNode { + public BehaviourTree(string name) : base(name) { + } + + public override Status Process(float dt) { + while (m_CurrentChild < Children.Count) { + Status status = Children[m_CurrentChild].Process(dt); + if (status != Status.Success) { + return status; + } + + m_CurrentChild += 1; + } + + return Status.Success; + } + } +} \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/BehaviourTree.cs.meta b/Runtime/Engine/Code/AI/BehaviourTree.cs.meta new file mode 100644 index 0000000..ccceb9c --- /dev/null +++ b/Runtime/Engine/Code/AI/BehaviourTree.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4ceac2e33fd54beebadb6e844f2a7328 +timeCreated: 1760017438 \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/IStrategy.cs b/Runtime/Engine/Code/AI/IStrategy.cs new file mode 100644 index 0000000..8eb4adb --- /dev/null +++ b/Runtime/Engine/Code/AI/IStrategy.cs @@ -0,0 +1,38 @@ +using System; + +namespace RebootKit.Engine.AI { + public interface IStrategy { + BehaviourNode.Status Process(float dt); + void Reset() { + } + } + + public class Condition : IStrategy { + readonly Func m_Predicate; + + public Condition(Func predicate) { + m_Predicate = predicate; + } + + public BehaviourNode.Status Process(float dt) { + if (m_Predicate()) { + return BehaviourNode.Status.Success; + } + + return BehaviourNode.Status.Failure; + } + } + + public class ActionStrategy : IStrategy { + readonly Action m_Action; + + public ActionStrategy(Action action) { + m_Action = action; + } + + public BehaviourNode.Status Process(float dt) { + m_Action(); + return BehaviourNode.Status.Success; + } + } +} \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/IStrategy.cs.meta b/Runtime/Engine/Code/AI/IStrategy.cs.meta new file mode 100644 index 0000000..4624337 --- /dev/null +++ b/Runtime/Engine/Code/AI/IStrategy.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 85b48e6160ad4f039e9a5fc6524472fc +timeCreated: 1760108175 \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/Leaf.cs b/Runtime/Engine/Code/AI/Leaf.cs new file mode 100644 index 0000000..0427a24 --- /dev/null +++ b/Runtime/Engine/Code/AI/Leaf.cs @@ -0,0 +1,17 @@ +namespace RebootKit.Engine.AI { + public class Leaf : BehaviourNode { + readonly IStrategy m_Strategy; + + public Leaf(string name, IStrategy strategy) : base(name) { + m_Strategy = strategy; + } + + public override Status Process(float dt) { + return m_Strategy.Process(dt); + } + + public override void Reset() { + m_Strategy.Reset(); + } + } +} \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/Leaf.cs.meta b/Runtime/Engine/Code/AI/Leaf.cs.meta new file mode 100644 index 0000000..00d7362 --- /dev/null +++ b/Runtime/Engine/Code/AI/Leaf.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ce3c5054b2fd45f6a5b26b74e735a622 +timeCreated: 1760108171 \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/Selector.cs b/Runtime/Engine/Code/AI/Selector.cs new file mode 100644 index 0000000..a205cae --- /dev/null +++ b/Runtime/Engine/Code/AI/Selector.cs @@ -0,0 +1,37 @@ +using System; + +namespace RebootKit.Engine.AI { + public class Selector : BehaviourNode { + readonly Func m_Condition; + + public Selector(string name, Func condition = null) : base(name) { + m_Condition = condition; + } + + public override Status Process(float dt) { + if (m_Condition != null && !m_Condition()) { + return Status.Failure; + } + + if (m_CurrentChild < Children.Count) { + Status status = Children[m_CurrentChild].Process(dt); + + switch (status) { + case Status.Success: + Reset(); + return Status.Success; + + case Status.Failure: + m_CurrentChild += 1; + return Status.Running; + + case Status.Running: + return Status.Running; + } + } + + Reset(); + return Status.Failure; + } + } +} \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/Selector.cs.meta b/Runtime/Engine/Code/AI/Selector.cs.meta new file mode 100644 index 0000000..ec0f9ca --- /dev/null +++ b/Runtime/Engine/Code/AI/Selector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ab99366791464e3789770f26559fa59a +timeCreated: 1760101875 \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/Sequence.cs b/Runtime/Engine/Code/AI/Sequence.cs new file mode 100644 index 0000000..f8b84fc --- /dev/null +++ b/Runtime/Engine/Code/AI/Sequence.cs @@ -0,0 +1,37 @@ +using System; + +namespace RebootKit.Engine.AI { + public class Sequence : BehaviourNode { + readonly Func m_Condition; + + public Sequence(string name, Func condition = null) : base(name) { + m_Condition = condition; + } + + public override Status Process(float dt) { + if (m_Condition != null && !m_Condition()) { + return Status.Failure; + } + + if (m_CurrentChild < Children.Count) { + Status status = Children[m_CurrentChild].Process(dt); + + switch (status) { + case Status.Success: + m_CurrentChild += 1; + return m_CurrentChild == Children.Count ? Status.Success : Status.Running; + + case Status.Failure: + Reset(); + return Status.Failure; + + case Status.Running: + return Status.Running; + } + } + + Reset(); + return Status.Success; + } + } +} \ No newline at end of file diff --git a/Runtime/Engine/Code/AI/Sequence.cs.meta b/Runtime/Engine/Code/AI/Sequence.cs.meta new file mode 100644 index 0000000..05f0599 --- /dev/null +++ b/Runtime/Engine/Code/AI/Sequence.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c49882ec0f3b4f28a2ed3491967fa966 +timeCreated: 1760101518 \ No newline at end of file