Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Assets/Samples/BehaviorTreeList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using CleverCrow.Fluid.BTs.Trees;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace CleverCrow.Fluid.BTs.Samples
{
public class BehaviorTreeList : MonoBehaviour
{
protected void Awake()
{
for (int i = 0; i < 3; i++)
{
trees.Add(new NestedTree()
{
tree = new BehaviorTreeBuilder(gameObject).Name($"Tree{i}").Sequence()
.WaitTime(1)
.ReturnSuccess()
.End().Build()
});
}
}
public List<NestedTree> trees = new List<NestedTree>();
}
[Serializable]
public class NestedTree
{
public BehaviorTree tree;
}
}
11 changes: 11 additions & 0 deletions Assets/Samples/BehaviorTreeList.cs.meta

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

154 changes: 143 additions & 11 deletions Assets/Samples/TreeSample.unity
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 11
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
Expand Down Expand Up @@ -98,13 +97,13 @@ LightmapSettings:
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
m_LightingSettings: {fileID: 1443705540}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
Expand All @@ -117,7 +116,9 @@ NavMeshSettings:
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
Expand Down Expand Up @@ -197,6 +198,7 @@ Light:
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_UseViewFrustumForShadowCasterCull: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &294120168
Expand All @@ -206,12 +208,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 294120166}
serializedVersion: 2
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &322793818
GameObject:
Expand Down Expand Up @@ -253,9 +256,17 @@ Camera:
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
Expand Down Expand Up @@ -289,12 +300,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 322793818}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &343368638
GameObject:
Expand Down Expand Up @@ -333,12 +345,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 343368638}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &533478364
GameObject:
Expand Down Expand Up @@ -369,18 +382,137 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 035df0b7568e1804f9b2f6dfb0bd0645, type: 3}
m_Name:
m_EditorClassIdentifier:
_toggle: 0
_isTaskSuccess: 0
--- !u!4 &533478366
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 533478364}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!850595691 &1443705540
LightingSettings:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Settings.lighting
serializedVersion: 6
m_GIWorkflowMode: 1
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_RealtimeEnvironmentLighting: 1
m_BounceScale: 1
m_AlbedoBoost: 1
m_IndirectOutputScale: 1
m_UsingShadowmask: 1
m_BakeBackend: 1
m_LightmapMaxSize: 1024
m_BakeResolution: 40
m_Padding: 2
m_LightmapCompression: 3
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAO: 0
m_MixedBakeMode: 2
m_LightmapsBakeMode: 1
m_FilterMode: 1
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_RealtimeResolution: 2
m_ForceWhiteAlbedo: 0
m_ForceUpdates: 0
m_FinalGather: 0
m_FinalGatherRayCount: 256
m_FinalGatherFiltering: 1
m_PVRCulling: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVREnvironmentSampleCount: 256
m_PVREnvironmentReferencePointCount: 2048
m_LightProbeSampleCountMultiplier: 4
m_PVRBounces: 2
m_PVRMinBounces: 2
m_PVREnvironmentImportanceSampling: 1
m_PVRFilteringMode: 1
m_PVRDenoiserTypeDirect: 1
m_PVRDenoiserTypeIndirect: 1
m_PVRDenoiserTypeAO: 1
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_PVRTiledBaking: 0
m_NumRaysToShootPerTexel: -1
m_RespectSceneVisibilityWhenBakingGI: 0
--- !u!1 &1786752064
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1786752065}
- component: {fileID: 1786752066}
m_Layer: 0
m_Name: BehaviorTreeList
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1786752065
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1786752064}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1786752066
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1786752064}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d249f0b66a31f2c41b4014c03856ae10, type: 3}
m_Name:
m_EditorClassIdentifier:
trees: []
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 322793821}
- {fileID: 294120168}
- {fileID: 343368640}
- {fileID: 533478366}
- {fileID: 1786752065}
Original file line number Diff line number Diff line change
@@ -1,21 +1,91 @@
using System;
using System.Collections;
using System.Reflection;
using UnityEditor;
using UnityEngine;

namespace CleverCrow.Fluid.BTs.Trees.Editors {
namespace CleverCrow.Fluid.BTs.Trees.Editors
{
[CustomPropertyDrawer(typeof(BehaviorTree))]
public class BehaviorTreeDrawer : PropertyDrawer {
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
public class BehaviorTreeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);

position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
GUI.enabled = Application.isPlaying;
if (GUI.Button(position, "View Tree")) {
var tree = fieldInfo.GetValue(property.serializedObject.targetObject) as IBehaviorTree;
BehaviorTreeWindow.ShowTree(tree, tree.Name ?? property.displayName);
if (GUI.Button(position, "View Tree"))
{
object value = GetTargetObjectOfProperty(property);
if (value is IBehaviorTree tree)
{
BehaviorTreeWindow.ShowTree(tree, tree.Name ?? property.displayName);
}
else
{
Debug.LogWarning($"BehaviorTreeDrawer: cannot resolve runtime value for property '{property.propertyPath}'.");
}
}
GUI.enabled = true;

EditorGUI.EndProperty();
}
public object GetTargetObjectOfProperty(SerializedProperty prop)
{
if (prop == null) return null;

object obj = prop.serializedObject.targetObject;
if (obj == null) return null;

string path = prop.propertyPath.Replace(".Array.data[", "[");
string[] elements = path.Split('.');

foreach (string element in elements)
{
if (element.Contains("["))
{
int indexStart = element.IndexOf("[", StringComparison.Ordinal);
string memberName = element.Substring(0, indexStart);
string indexStr = element.Substring(indexStart)
.Trim('[', ']');

obj = GetMemberValue(obj, memberName);

if (obj is IList list && int.TryParse(indexStr, out int index) && index >= 0 && index < list.Count)
{
obj = list[index];
}
else
{
return null;
}
}
else
{
obj = GetMemberValue(obj, element);
}

if (obj == null)
return null;
}

return obj;
}

private object GetMemberValue(object source, string name)
{
if (source == null)
return null;
var type = source.GetType();

const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

FieldInfo field = type.GetField(name, flags);
if (field != null)
return field.GetValue(source);

return null;
}
}
}
Loading