add unity behavior package & examples

add behavior tree implementation
This commit is contained in:
2025-04-23 18:10:17 +02:00
parent 4602ff2416
commit a97b3be68a
34 changed files with 3675 additions and 92 deletions
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0e73928b0a104233917799d1897dd859
timeCreated: 1745423479
+10
View File
@@ -0,0 +1,10 @@
namespace DefaultNamespace.BehaviorTree
{
public abstract class Action : Node
{
public Action()
{
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cc1cb3b6c7d74fc28fd7b6399bd09156
timeCreated: 1745423851
@@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace DefaultNamespace.BehaviorTree
{
public abstract class Composite : Node
{
public Composite(List<Node> nodes)
{
_nodes.AddRange(nodes);
}
public Composite(params Node[] nodes)
{
_nodes.AddRange(nodes);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 137c1749ac9748599a82996a6a005d54
timeCreated: 1745423923
@@ -0,0 +1,7 @@
namespace DefaultNamespace.BehaviorTree
{
public abstract class Condition : Action
{
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bfc01cdaf36045d3be75ac78fc1f0feb
timeCreated: 1745424014
@@ -0,0 +1,10 @@
namespace DefaultNamespace.BehaviorTree
{
public class Decorator : Node
{
public Decorator(Node node)
{
_nodes.Add(node);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8c98374aeec84c929927512d23f6631f
timeCreated: 1745423985
+31
View File
@@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace DefaultNamespace.BehaviorTree
{
public abstract class Node
{
protected List<Node> _nodes = new ();
public virtual void Start()
{
}
public virtual Status Update()
{
return Status.Failure;
}
public virtual void End()
{
}
}
public enum Status
{
Success,
Failure,
Running,
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 086671579f914f31839c05dbdc541e33
timeCreated: 1745423564
@@ -0,0 +1,42 @@
using System;
namespace DefaultNamespace.BehaviorTree
{
public class Sequence : Composite
{
private int _currentIndex;
private Node _currentNode;
public override void Start()
{
_currentIndex = 0;
_currentNode = _nodes == null || _nodes.Count == 0 ? null : _nodes[_currentIndex];
_currentNode?.Start();
}
public override Status Update()
{
if (_currentNode == null) return Status.Failure;
Status status = _currentNode.Update();
switch (status)
{
case Status.Success:
_currentIndex++;
_currentNode.End();
if (_currentIndex >= _nodes.Count) return Status.Success;
_currentNode = _nodes[_currentIndex];
_currentNode?.Start();
return Status.Running;
case Status.Failure:
return Status.Failure;
case Status.Running:
return Status.Running;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 817cdc9a926641068ccf01671393272d
timeCreated: 1745424048
+25
View File
@@ -0,0 +1,25 @@
using System;
using UnityEngine;
namespace DefaultNamespace.BehaviorTree
{
public class Tree : MonoBehaviour
{
private Node _rootNode;
private void OnEnable()
{
_rootNode?.Start();
}
private void Update()
{
_rootNode?.Update();
}
private void OnDisable()
{
_rootNode?.End();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d2cbbd082c73432ca7bc1d76ac315ebe
timeCreated: 1745423498
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 90aacf97469f84a1ba368dd1edaf400d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,48 @@
using System;
using DefaultNamespace;
using DefaultNamespace.FSM;
using Unity.Behavior;
using UnityEngine;
using Action = Unity.Behavior.Action;
using Unity.Properties;
[Serializable, GeneratePropertyBag]
[NodeDescription(name: "Find Player Controller By Raycast", story: "Find [Target] by Raycast from [Agent]", category: "Action/Find", id: "e2b3bc47cdb71b5678009c1d431fc68b")]
public partial class FindPlayerControllerByRaycastAction : Action
{
[SerializeReference] public BlackboardVariable<GameObject> Target;
[SerializeReference] public BlackboardVariable<GameObject> Agent;
[SerializeReference] public BlackboardVariable<float> MaxDistance = new(100);
protected override Status OnStart()
{
// setup node
// Target.Value = null;
// check initial values
if (Agent.Value == null) return Status.Failure;
return Status.Running;
}
protected override Status OnUpdate()
{
if (Physics.Raycast(Agent.Value.transform.position, Agent.Value.transform.forward, out RaycastHit hit,
MaxDistance))
{
if (hit.transform.GetComponent<PlayerController>() != null)
{
Target.Value = hit.transform.gameObject;
return Status.Success;
}
}
Target.Value = null;
return Status.Failure;
}
protected override void OnEnd()
{
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6a08b2b3e631346b2b155982df199f9a
@@ -0,0 +1,24 @@
using System;
using Unity.Behavior;
using UnityEngine;
[Serializable, Unity.Properties.GeneratePropertyBag]
[Condition(name: "GameObject is Null", story: "[Object] is [IsNull] null", category: "Variable Conditions", id: "9be617c0444353affee2f412e94ae715")]
public partial class GameObjectNullCondition : Condition
{
[SerializeReference] public BlackboardVariable<GameObject> Object;
[SerializeReference] public BlackboardVariable<bool> IsNull;
public override bool IsTrue()
{
return (Object.Value == null && IsNull) || (Object.Value != null && !IsNull);
}
public override void OnStart()
{
}
public override void OnEnd()
{
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 534847d817af848138303989d8adde9b