├── .gitignore
├── Example
├── example.unity.meta
├── Waypoint
│ ├── Waypoint.cs
│ ├── WaypointHolder.cs
│ ├── Waypoint.cs.meta
│ └── WaypointHolder.cs.meta
├── Resources.meta
├── Waypoint.meta
├── RedSphereTree.cs
├── Resources
│ ├── blue.mat.meta
│ ├── redmetal.mat.meta
│ ├── redmetal.mat
│ └── blue.mat
├── MovementController.cs
├── PatrolWaypoints.cs.meta
├── RedSphereBehaviour.cs
├── RedSphereTree.cs.meta
├── MovementController.cs.meta
├── RedSphereBehaviour.cs.meta
├── PatrolWaypoints.cs
└── example.unity
├── src
├── Node
│ ├── LeafNodes
│ │ └── EmptyNode.cs
│ ├── DecoratorNode.cs
│ ├── Node.cs
│ ├── DecoratorNodes
│ │ ├── SucceederNode.cs
│ │ ├── RepeaterNode.cs
│ │ ├── BreakpointNode.cs
│ │ ├── InverterNode.cs
│ │ └── RepeatUntilFailNode.cs
│ ├── LeafNode.cs
│ ├── ParentNode.cs
│ ├── CompositeNodes
│ │ ├── SelectorNode.cs
│ │ ├── SequenceNode.cs
│ │ └── ParallelNode.cs
│ └── CompositeNode.cs
├── UtilityNodes
│ └── TimedNoBehaviour.cs
├── BehaviourTree.cs
└── Contexts
│ └── Context.cs
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.meta
--------------------------------------------------------------------------------
/Example/example.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8cdde4867416ac54dbdd27fadafb6158
3 | timeCreated: 1527055888
4 | licenseType: Free
5 | DefaultImporter:
6 | externalObjects: {}
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Example/Waypoint/Waypoint.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | ///
6 | /// Example class representing a waypoint in the world.
7 | ///
8 | public class Waypoint : MonoBehaviour {
9 | }
10 |
--------------------------------------------------------------------------------
/Example/Resources.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b22d7b97ec43c9846908db5381b89f67
3 | folderAsset: yes
4 | timeCreated: 1527055546
5 | licenseType: Free
6 | DefaultImporter:
7 | externalObjects: {}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Example/Waypoint.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 44979c67c6d7f8b4fbf27750e306b3f1
3 | folderAsset: yes
4 | timeCreated: 1527119529
5 | licenseType: Free
6 | DefaultImporter:
7 | externalObjects: {}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Example/RedSphereTree.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | public class RedSphereTree : BehaviourTree {
6 |
7 | protected override Node DefineBehaviour()
8 | {
9 | return new RedSphereBehaviour();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Example/Resources/blue.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3aa0fa22682631942a3837e3d223b319
3 | timeCreated: 1527055554
4 | licenseType: Free
5 | NativeFormatImporter:
6 | externalObjects: {}
7 | mainObjectFileID: 2100000
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Example/Resources/redmetal.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f56bc685b518fd942a38e670388db070
3 | timeCreated: 1527055554
4 | licenseType: Free
5 | NativeFormatImporter:
6 | externalObjects: {}
7 | mainObjectFileID: 2100000
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Example/MovementController.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | public class MovementController : MonoBehaviour {
6 |
7 | // Use this for initialization
8 | void Start () {
9 |
10 | }
11 |
12 | // Update is called once per frame
13 | void Update () {
14 |
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Example/Waypoint/WaypointHolder.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | ///
6 | /// Example class which allows for assignment of a set of waypoints in the inspector.
7 | ///
8 | public class WaypointHolder : MonoBehaviour
9 | {
10 | public Waypoint[] waypoints;
11 | }
12 |
--------------------------------------------------------------------------------
/Example/PatrolWaypoints.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0c502d8587ff99e45b6e55117cba8f8b
3 | timeCreated: 1527125950
4 | licenseType: Free
5 | MonoImporter:
6 | externalObjects: {}
7 | serializedVersion: 2
8 | defaultReferences: []
9 | executionOrder: 0
10 | icon: {instanceID: 0}
11 | userData:
12 | assetBundleName:
13 | assetBundleVariant:
14 |
--------------------------------------------------------------------------------
/Example/RedSphereBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | public class RedSphereBehaviour : ParentNode {
6 |
7 | protected override Node DefineBehaviour()
8 | {
9 | return new RepeaterNode(
10 | new SequenceNode(new TimedNoBehaviour(5f), new PatrolWaypoints())
11 | );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Example/RedSphereTree.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3f9d7d6484b685c4aaf20be9b7610268
3 | timeCreated: 1527128555
4 | licenseType: Free
5 | MonoImporter:
6 | externalObjects: {}
7 | serializedVersion: 2
8 | defaultReferences: []
9 | executionOrder: 0
10 | icon: {instanceID: 0}
11 | userData:
12 | assetBundleName:
13 | assetBundleVariant:
14 |
--------------------------------------------------------------------------------
/Example/MovementController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 89be78a03013e4a4f9310034014182ee
3 | timeCreated: 1527127678
4 | licenseType: Free
5 | MonoImporter:
6 | externalObjects: {}
7 | serializedVersion: 2
8 | defaultReferences: []
9 | executionOrder: 0
10 | icon: {instanceID: 0}
11 | userData:
12 | assetBundleName:
13 | assetBundleVariant:
14 |
--------------------------------------------------------------------------------
/Example/RedSphereBehaviour.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 30353ac186c021e4fbf007fce82fdc82
3 | timeCreated: 1527128434
4 | licenseType: Free
5 | MonoImporter:
6 | externalObjects: {}
7 | serializedVersion: 2
8 | defaultReferences: []
9 | executionOrder: 0
10 | icon: {instanceID: 0}
11 | userData:
12 | assetBundleName:
13 | assetBundleVariant:
14 |
--------------------------------------------------------------------------------
/Example/Waypoint/Waypoint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 55b1bdb9d4b2b0342b8fc84328b71c30
3 | timeCreated: 1527119524
4 | licenseType: Free
5 | MonoImporter:
6 | externalObjects: {}
7 | serializedVersion: 2
8 | defaultReferences: []
9 | executionOrder: 0
10 | icon: {instanceID: 0}
11 | userData:
12 | assetBundleName:
13 | assetBundleVariant:
14 |
--------------------------------------------------------------------------------
/src/Node/LeafNodes/EmptyNode.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | //This node runs for one tick and is always a success.
6 | public class EmptyNode : LeafNode
7 | {
8 | protected override NodeStatus OnTick(Context context)
9 | {
10 | return NodeStatus.Success;
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/Example/Waypoint/WaypointHolder.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0a42377429ca0704eadf2a777daf71e4
3 | timeCreated: 1527119516
4 | licenseType: Free
5 | MonoImporter:
6 | externalObjects: {}
7 | serializedVersion: 2
8 | defaultReferences: []
9 | executionOrder: 0
10 | icon: {instanceID: 0}
11 | userData:
12 | assetBundleName:
13 | assetBundleVariant:
14 |
--------------------------------------------------------------------------------
/src/Node/DecoratorNode.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | ///
6 | /// A decorator node has a single child, and affects it's behaviour in some way.
7 | ///
8 | public abstract class DecoratorNode : Node {
9 |
10 | protected Node Child;
11 |
12 | protected DecoratorNode(Node child)
13 | {
14 | Child = child;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Node/Node.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | ///
6 | /// Parent class for all nodes.
7 | ///
8 | public abstract class Node
9 | {
10 | public enum NodeStatus {Running, Fail, Success}
11 |
12 | public abstract NodeStatus Tick(Context context);
13 |
14 | protected virtual void Init() {}
15 |
16 | public Node()
17 | {
18 | Init();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Node/DecoratorNodes/SucceederNode.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | ///
6 | /// This node always returns a success.
7 | ///
8 | public class SucceederNode : DecoratorNode {
9 |
10 | public SucceederNode(Node child) : base(child)
11 | {
12 | }
13 |
14 | public override NodeStatus Tick(Context context)
15 | {
16 | Child.Tick(context);
17 | return NodeStatus.Success;
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/Node/LeafNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Runtime.CompilerServices;
5 | using UnityEngine;
6 |
7 | ///
8 | /// Leaf nodes have no children and are intended to hold behaviours.
9 | ///
10 | public abstract class LeafNode : Node
11 | {
12 | public sealed override NodeStatus Tick(Context context)
13 | {
14 | NodeStatus n = OnTick(context);
15 | return n;
16 | }
17 |
18 | protected abstract NodeStatus OnTick(Context context);
19 | }
20 |
--------------------------------------------------------------------------------
/src/Node/DecoratorNodes/RepeaterNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// Repeats the child node on failure.
8 | /// Use sparingly as this can lead to undesirable behaviour loops.
9 | /// Should be the parent node of every behaviourTree.
10 | ///
11 | public class RepeaterNode : DecoratorNode {
12 |
13 | public RepeaterNode(Node child) : base(child)
14 | {
15 | }
16 |
17 | public override NodeStatus Tick(Context context)
18 | {
19 | Child.Tick(context);
20 | return NodeStatus.Running;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Node/ParentNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// A node with a function which allows it to define it's own child.
8 | /// Good for use as a starting node in a behaviourtree.
9 | ///
10 | public abstract class ParentNode : Node
11 | {
12 | protected Node Child;
13 | protected override void Init()
14 | {
15 | Child = DefineBehaviour();
16 | }
17 |
18 | protected abstract Node DefineBehaviour();
19 |
20 | public override NodeStatus Tick(Context context)
21 | {
22 | return Child.Tick(context);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/UtilityNodes/TimedNoBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | public class TimedNoBehaviour : LeafNode
6 | {
7 | private Timer _timer;
8 |
9 | ///
10 | /// Returns success after a given time.
11 | ///
12 | /// How long to wait before returning success.
13 | public TimedNoBehaviour(float seconds)
14 | {
15 | _timer = new Timer(seconds);
16 | }
17 | protected override NodeStatus OnTick(Context context)
18 | {
19 | _timer.Update();
20 |
21 | if (!_timer.IsComplete)
22 | {
23 | return NodeStatus.Running;
24 | }
25 |
26 | _timer.Reset();
27 | return NodeStatus.Success;
28 |
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/Node/DecoratorNodes/BreakpointNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// Breakpoints will stop the execution of their child if their condition is not met.
8 | ///
9 | public abstract class BreakpointNode : DecoratorNode
10 | {
11 | protected BreakpointNode(Node child) : base(child)
12 | {
13 | }
14 |
15 | ///
16 | /// Checks a condition to decide whether to break or not.
17 | /// If the condition is met, return true.
18 | ///
19 | ///
20 | protected abstract bool CheckCondition(Context context);
21 |
22 | public override NodeStatus Tick(Context context)
23 | {
24 | return !CheckCondition(context) ? NodeStatus.Fail : Child.Tick(context);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/Node/DecoratorNodes/InverterNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// Inverter nodes return the opposite result of their child.
8 | ///
9 | public class InverterNode : DecoratorNode {
10 |
11 | public InverterNode(Node child) : base(child)
12 | {
13 | }
14 |
15 | public override NodeStatus Tick(Context context)
16 | {
17 | var status = Child.Tick(context);
18 |
19 | switch (status) {
20 | case NodeStatus.Running:
21 | return NodeStatus.Running;
22 | case NodeStatus.Fail:
23 | return NodeStatus.Success;
24 | case NodeStatus.Success:
25 | return NodeStatus.Fail;
26 | default:
27 | throw new ArgumentOutOfRangeException();
28 | }
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Node/DecoratorNodes/RepeatUntilFailNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// Node that repeats operation of the child until it fails.
8 | ///
9 | public class RepeatUntilFailNode : DecoratorNode {
10 |
11 | public RepeatUntilFailNode(Node child) : base(child)
12 | {
13 | }
14 |
15 | public override NodeStatus Tick(Context context)
16 | {
17 | var status = Child.Tick(context);
18 |
19 | switch (status)
20 | {
21 | case NodeStatus.Running:
22 | return NodeStatus.Running;
23 | case NodeStatus.Fail:
24 | return NodeStatus.Fail;
25 | case NodeStatus.Success:
26 | return NodeStatus.Running;
27 | default:
28 | throw new ArgumentOutOfRangeException();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/BehaviourTree.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | public abstract class BehaviourTree : MonoBehaviour
6 | {
7 | protected Context Context;
8 |
9 | ///
10 | /// The starting node to ping.
11 | /// Usually, a Repeaternode.
12 | ///
13 | private Node _parentNode;
14 |
15 | private void Awake()
16 | {
17 | OnAwake();
18 | }
19 |
20 | private void Start()
21 | {
22 | Context = new Context(gameObject);
23 | _parentNode = DefineBehaviour();
24 | }
25 |
26 | protected virtual void OnAwake()
27 | {
28 | }
29 |
30 | ///
31 | /// Define the behavior in this method and return the parent node.
32 | ///
33 | ///
34 | protected abstract Node DefineBehaviour();
35 |
36 | private void FixedUpdate()
37 | {
38 | _parentNode.Tick(Context);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Node/CompositeNodes/SelectorNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// Runs all children until a success is reached, and fails if each node has failed.
8 | ///
9 | public class SelectorNode : CompositeNode {
10 |
11 | public override NodeStatus Tick(Context context)
12 | {
13 | var status = Children[ActiveNodeIndex].Tick(context);
14 |
15 | switch (status) {
16 | case NodeStatus.Running:
17 | return NodeStatus.Running;
18 | case NodeStatus.Fail:
19 | var allNodesFailed = !TryMoveToNextNode();
20 | return allNodesFailed ? NodeStatus.Fail : NodeStatus.Running;
21 | case NodeStatus.Success:
22 | return NodeStatus.Success;
23 | default:
24 | throw new ArgumentOutOfRangeException();
25 | }
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Node/CompositeNode.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 |
4 | ///
5 | /// Composite nodes have one or more children.
6 | ///
7 | public abstract class CompositeNode : Node
8 | {
9 | protected List Children = new List();
10 |
11 | protected int ActiveNodeIndex;
12 |
13 | protected CompositeNode(params Node[] childNodes)
14 | {
15 | if (childNodes.Length <= 0)
16 | {
17 | Children.Add(new EmptyNode());
18 | }
19 |
20 | foreach (var n in childNodes)
21 | {
22 | Children.Add(n);
23 | }
24 | }
25 |
26 | protected void Reset()
27 | {
28 | ActiveNodeIndex = 0;
29 | }
30 |
31 | protected bool TryMoveToNextNode()
32 | {
33 | if (ActiveNodeIndex < Children.Count - 1 )
34 | {
35 | ActiveNodeIndex++;
36 | return true;
37 | }
38 | else
39 | {
40 | ActiveNodeIndex = 0;
41 | return false;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Node/CompositeNodes/SequenceNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// SequenceNodes have a "Complete" status when the sequence was successfully executed.
8 | ///
9 | public class SequenceNode : CompositeNode
10 | {
11 | public SequenceNode(params Node[] childNodes) : base(childNodes)
12 | {
13 | }
14 |
15 | public override NodeStatus Tick(Context context)
16 | {
17 | NodeStatus result = Children[ActiveNodeIndex].Tick(context);
18 |
19 | switch (result)
20 | {
21 | case NodeStatus.Running:
22 | return NodeStatus.Running;
23 | case NodeStatus.Fail:
24 | Reset();
25 | return NodeStatus.Fail;
26 | case NodeStatus.Success:
27 | var sequenceComplete = !TryMoveToNextNode();
28 | return sequenceComplete ? NodeStatus.Success : NodeStatus.Running;
29 | default:
30 | throw new ArgumentOutOfRangeException();
31 | }
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Example/PatrolWaypoints.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | public class PatrolWaypoints : LeafNode
6 | {
7 | private int current_waypoint = 0;
8 |
9 | protected override NodeStatus OnTick(Context context)
10 | {
11 | Debug.Log(context);
12 | Debug.Log(context.agent);
13 | var wpholder = context.agent.GetComponent();
14 | //If the agent has no WPholder, or if the wpholder is empty, return failure
15 | if (wpholder == null || wpholder.waypoints.Length == 0)
16 | {
17 | return NodeStatus.Fail;
18 | }
19 |
20 | //Translate towards waypoint
21 | context.agent.transform.position =
22 | Vector3.MoveTowards(context.agent.transform.position,
23 | wpholder.waypoints[current_waypoint].transform.position, .2f);
24 |
25 | //Measure how close the object is to it's destination
26 | var closeness =
27 | (context.agent.transform.position - wpholder.waypoints[current_waypoint].transform.position).magnitude;
28 |
29 | if (closeness > 1f)
30 | {
31 | return NodeStatus.Running;
32 | }
33 |
34 | //If we were close enough, move onto the next waypoint.
35 | current_waypoint += 1;
36 | if (current_waypoint < wpholder.waypoints.Length)
37 | {
38 | return NodeStatus.Running;
39 | }
40 |
41 | //We're done, reset the current wp and return a success
42 | current_waypoint = 0;
43 | return NodeStatus.Success;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Umbrella Tree
2 |
3 |
4 | Umbrella Tree is a skeletal, bare-bones implementation of an AI behaviour tree for your next Unity project. Umbrella Tree is designed to use no dependencies on other assets or code (and even limits it's interface with the Unity editor). The design of the tree is based on [this excellent blog post by Chris Simpson](https://www.gamasutra.com/blogs/ChrisSimpson/20140717/221339/Behavior_trees_for_AI_How_they_work.php), except it is written in C# and requires no XML.
5 |
6 |
7 |
8 |
9 | ## Installation
10 |
11 |
12 | Download and extract the files in SRC to your Unity project. You're done!
13 |
14 |
15 |
16 | ## Usage
17 |
18 |
19 | 1. Create a new Component that inherits from BehaviourTree. Also, create LeafNodes encapsulating individual behaviours.
20 |
21 | 2. Define your tree with your nodes.. Start with a ParentNode. For an example, see the RedSphereBehaviour node in /example.
22 |
23 | 3. Add the new Component to the object which you wish to behave.
24 |
25 | 4. You're done! The hard part is writing the LeafNode behaviours.
26 |
27 |
28 |
29 | ## Contexts
30 |
31 |
32 | Each of your nodes will have access to a Context object which is per-object. The Context object extends the functionality of the tree by adding access to semi-global context variables. You can add keyed data to the context with SetContextData and recover keyed data of an expected type by using GetContextData\. **Avoid using context variables unless it is really necessary. Abuse of context variables will invariably overcomplicate your tree.**
33 |
34 |
35 |
36 | ## Contact
37 |
38 | Please raise GitHub issues on this project if you feel like Umbrella Tree is missing a feature or has a bug.
39 |
--------------------------------------------------------------------------------
/src/Node/CompositeNodes/ParallelNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | ///
7 | /// A node which runs all children at the same time. The node decides it's state when the node success rate is either
8 | /// above (sucess) or below (fail) the supplied success rate.
9 | ///
10 | public class ParallelNode : CompositeNode
11 | {
12 | private readonly float _requiredSuccesses;
13 |
14 | ///
15 | /// Build a new ParallelNode.
16 | ///
17 | /// The required success rate as a percent (0-1f)
18 | /// The nodes to run in sequence.
19 | protected ParallelNode(float requiredSuccessRate, params Node[] childNodes) : base(childNodes)
20 | {
21 | requiredSuccessRate.ClampTo(new Range(0f, 1f));
22 | _requiredSuccesses = (int)Math.Floor(Children.Count * requiredSuccessRate);
23 | }
24 |
25 | public override NodeStatus Tick(Context context)
26 | {
27 | var successes = 0;
28 |
29 | foreach (var n in Children)
30 | {
31 | var status = n.Tick(context);
32 | switch (status)
33 | {
34 | case NodeStatus.Running:
35 | break;
36 | case NodeStatus.Fail:
37 | break;
38 | case NodeStatus.Success:
39 | successes++;
40 | break;
41 | default:
42 | throw new ArgumentOutOfRangeException();
43 | }
44 | }
45 |
46 | return successes >= _requiredSuccesses ? NodeStatus.Success : NodeStatus.Running;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Contexts/Context.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using NUnit.Framework;
6 | using UnityEditor;
7 | using UnityEngine;
8 | using UnityEngine.AI;
9 |
10 | public sealed class Context
11 | {
12 | public readonly GameObject agent;
13 |
14 | private readonly Dictionary contextData = new Dictionary();
15 |
16 | public Context(GameObject agent)
17 | {
18 | this.agent = agent;
19 | }
20 |
21 | public void SetContextData(string name, object data)
22 | {
23 | contextData[name] = data;
24 | }
25 |
26 | ///
27 | /// Get data from the context.
28 | ///
29 | /// The expected name of the data.
30 | ///
31 | /// The data if it exists, and the default value if it does not.
32 | public T TryGetContextData(string name)
33 | {
34 | if (!dataExists(name))
35 | {
36 | Debug.LogFormat("Tried to find a {0}-type object named '{1}', but it was either of the wrong type" +
37 | "or it did not exist.", name, typeof(T));
38 | return default(T);
39 | }
40 |
41 | return (T) contextData[name];
42 | }
43 |
44 | ///
45 | /// Does the data exist at this label?
46 | ///
47 | ///
48 | ///
49 | public bool dataExists(string label)
50 | {
51 | return contextData.Keys.Contains(label) && contextData["label"].GetType() == typeof(T);
52 | }
53 |
54 | ///
55 | /// Dumps the context's data including names. This allows for easy debugging.
56 | ///
57 | public void DumpData()
58 | {
59 | var result = string.Format("Context data members for {1}: ");
60 | foreach (var entry in contextData)
61 | {
62 | result += string.Format("{0}:{1} of type {2}", entry.Key, entry.Value, entry.Value.GetType());
63 | }
64 | Debug.Log(result);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Example/Resources/redmetal.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_PrefabParentObject: {fileID: 0}
8 | m_PrefabInternal: {fileID: 0}
9 | m_Name: redmetal
10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
11 | m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
12 | m_LightmapFlags: 4
13 | m_EnableInstancingVariants: 0
14 | m_DoubleSidedGI: 0
15 | m_CustomRenderQueue: -1
16 | stringTagMap: {}
17 | disabledShaderPasses: []
18 | m_SavedProperties:
19 | serializedVersion: 3
20 | m_TexEnvs:
21 | - _BumpMap:
22 | m_Texture: {fileID: 0}
23 | m_Scale: {x: 1, y: 1}
24 | m_Offset: {x: 0, y: 0}
25 | - _DetailAlbedoMap:
26 | m_Texture: {fileID: 0}
27 | m_Scale: {x: 1, y: 1}
28 | m_Offset: {x: 0, y: 0}
29 | - _DetailMask:
30 | m_Texture: {fileID: 0}
31 | m_Scale: {x: 1, y: 1}
32 | m_Offset: {x: 0, y: 0}
33 | - _DetailNormalMap:
34 | m_Texture: {fileID: 0}
35 | m_Scale: {x: 1, y: 1}
36 | m_Offset: {x: 0, y: 0}
37 | - _EmissionMap:
38 | m_Texture: {fileID: 0}
39 | m_Scale: {x: 1, y: 1}
40 | m_Offset: {x: 0, y: 0}
41 | - _MainTex:
42 | m_Texture: {fileID: 0}
43 | m_Scale: {x: 1, y: 1}
44 | m_Offset: {x: 0, y: 0}
45 | - _MetallicGlossMap:
46 | m_Texture: {fileID: 0}
47 | m_Scale: {x: 1, y: 1}
48 | m_Offset: {x: 0, y: 0}
49 | - _OcclusionMap:
50 | m_Texture: {fileID: 0}
51 | m_Scale: {x: 1, y: 1}
52 | m_Offset: {x: 0, y: 0}
53 | - _ParallaxMap:
54 | m_Texture: {fileID: 0}
55 | m_Scale: {x: 1, y: 1}
56 | m_Offset: {x: 0, y: 0}
57 | m_Floats:
58 | - _BumpScale: 1
59 | - _Cutoff: 0.5
60 | - _DetailNormalMapScale: 1
61 | - _DstBlend: 0
62 | - _GlossMapScale: 0.459
63 | - _Glossiness: 0.543
64 | - _GlossyReflections: 0
65 | - _Metallic: 0.635
66 | - _Mode: 0
67 | - _OcclusionStrength: 1
68 | - _Parallax: 0.02
69 | - _SmoothnessTextureChannel: 1
70 | - _SpecularHighlights: 1
71 | - _SrcBlend: 1
72 | - _UVSec: 0
73 | - _ZWrite: 1
74 | m_Colors:
75 | - _Color: {r: 1, g: 0.27205884, b: 0.27205884, a: 0.822}
76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
77 |
--------------------------------------------------------------------------------
/Example/Resources/blue.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_PrefabParentObject: {fileID: 0}
8 | m_PrefabInternal: {fileID: 0}
9 | m_Name: blue
10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
11 | m_ShaderKeywords: _EMISSION _GLOSSYREFLECTIONS_OFF _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
12 | m_LightmapFlags: 1
13 | m_EnableInstancingVariants: 0
14 | m_DoubleSidedGI: 0
15 | m_CustomRenderQueue: -1
16 | stringTagMap: {}
17 | disabledShaderPasses: []
18 | m_SavedProperties:
19 | serializedVersion: 3
20 | m_TexEnvs:
21 | - _BumpMap:
22 | m_Texture: {fileID: 0}
23 | m_Scale: {x: 1, y: 1}
24 | m_Offset: {x: 0, y: 0}
25 | - _DetailAlbedoMap:
26 | m_Texture: {fileID: 0}
27 | m_Scale: {x: 1, y: 1}
28 | m_Offset: {x: 0, y: 0}
29 | - _DetailMask:
30 | m_Texture: {fileID: 0}
31 | m_Scale: {x: 1, y: 1}
32 | m_Offset: {x: 0, y: 0}
33 | - _DetailNormalMap:
34 | m_Texture: {fileID: 0}
35 | m_Scale: {x: 1, y: 1}
36 | m_Offset: {x: 0, y: 0}
37 | - _EmissionMap:
38 | m_Texture: {fileID: 0}
39 | m_Scale: {x: 1, y: 1}
40 | m_Offset: {x: 0, y: 0}
41 | - _MainTex:
42 | m_Texture: {fileID: 0}
43 | m_Scale: {x: 1, y: 1}
44 | m_Offset: {x: 0, y: 0}
45 | - _MetallicGlossMap:
46 | m_Texture: {fileID: 0}
47 | m_Scale: {x: 1, y: 1}
48 | m_Offset: {x: 0, y: 0}
49 | - _OcclusionMap:
50 | m_Texture: {fileID: 0}
51 | m_Scale: {x: 1, y: 1}
52 | m_Offset: {x: 0, y: 0}
53 | - _ParallaxMap:
54 | m_Texture: {fileID: 0}
55 | m_Scale: {x: 1, y: 1}
56 | m_Offset: {x: 0, y: 0}
57 | - _SpecGlossMap:
58 | m_Texture: {fileID: 0}
59 | m_Scale: {x: 1, y: 1}
60 | m_Offset: {x: 0, y: 0}
61 | m_Floats:
62 | - _BumpScale: 1
63 | - _Cutoff: 0.5
64 | - _DetailNormalMapScale: 1
65 | - _DstBlend: 0
66 | - _GlossMapScale: 0.459
67 | - _Glossiness: 0
68 | - _GlossyReflections: 0
69 | - _Metallic: 0
70 | - _Mode: 0
71 | - _OcclusionStrength: 1
72 | - _Parallax: 0.02
73 | - _SmoothnessTextureChannel: 1
74 | - _SpecularHighlights: 1
75 | - _SrcBlend: 1
76 | - _UVSec: 0
77 | - _ZWrite: 1
78 | m_Colors:
79 | - _Color: {r: 0.26275954, g: 0.66176474, b: 0.6122331, a: 0.822}
80 | - _EmissionColor: {r: 0.08616177, g: 0.41960663, b: 0.434, a: 1}
81 | - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
82 |
--------------------------------------------------------------------------------
/Example/example.unity:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!29 &1
4 | OcclusionCullingSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_OcclusionBakeSettings:
8 | smallestOccluder: 5
9 | smallestHole: 0.25
10 | backfaceThreshold: 100
11 | m_SceneGUID: 00000000000000000000000000000000
12 | m_OcclusionCullingData: {fileID: 0}
13 | --- !u!104 &2
14 | RenderSettings:
15 | m_ObjectHideFlags: 0
16 | serializedVersion: 8
17 | m_Fog: 0
18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
19 | m_FogMode: 3
20 | m_FogDensity: 0.01
21 | m_LinearFogStart: 0
22 | m_LinearFogEnd: 300
23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
26 | m_AmbientIntensity: 1
27 | m_AmbientMode: 0
28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
30 | m_HaloStrength: 0.5
31 | m_FlareStrength: 1
32 | m_FlareFadeSpeed: 3
33 | m_HaloTexture: {fileID: 0}
34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
35 | m_DefaultReflectionMode: 0
36 | m_DefaultReflectionResolution: 128
37 | m_ReflectionBounces: 1
38 | m_ReflectionIntensity: 1
39 | m_CustomReflection: {fileID: 0}
40 | m_Sun: {fileID: 0}
41 | m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074014, b: 0.3587274, a: 1}
42 | --- !u!157 &3
43 | LightmapSettings:
44 | m_ObjectHideFlags: 0
45 | serializedVersion: 11
46 | m_GIWorkflowMode: 0
47 | m_GISettings:
48 | serializedVersion: 2
49 | m_BounceScale: 1
50 | m_IndirectOutputScale: 1
51 | m_AlbedoBoost: 1
52 | m_TemporalCoherenceThreshold: 1
53 | m_EnvironmentLightingMode: 0
54 | m_EnableBakedLightmaps: 1
55 | m_EnableRealtimeLightmaps: 1
56 | m_LightmapEditorSettings:
57 | serializedVersion: 9
58 | m_Resolution: 2
59 | m_BakeResolution: 40
60 | m_TextureWidth: 1024
61 | m_TextureHeight: 1024
62 | m_AO: 0
63 | m_AOMaxDistance: 1
64 | m_CompAOExponent: 1
65 | m_CompAOExponentDirect: 0
66 | m_Padding: 2
67 | m_LightmapParameters: {fileID: 0}
68 | m_LightmapsBakeMode: 1
69 | m_TextureCompression: 1
70 | m_FinalGather: 0
71 | m_FinalGatherFiltering: 1
72 | m_FinalGatherRayCount: 256
73 | m_ReflectionCompression: 2
74 | m_MixedBakeMode: 2
75 | m_BakeBackend: 0
76 | m_PVRSampling: 1
77 | m_PVRDirectSampleCount: 32
78 | m_PVRSampleCount: 500
79 | m_PVRBounces: 2
80 | m_PVRFilterTypeDirect: 0
81 | m_PVRFilterTypeIndirect: 0
82 | m_PVRFilterTypeAO: 0
83 | m_PVRFilteringMode: 1
84 | m_PVRCulling: 1
85 | m_PVRFilteringGaussRadiusDirect: 1
86 | m_PVRFilteringGaussRadiusIndirect: 5
87 | m_PVRFilteringGaussRadiusAO: 2
88 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5
89 | m_PVRFilteringAtrousPositionSigmaIndirect: 2
90 | m_PVRFilteringAtrousPositionSigmaAO: 1
91 | m_ShowResolutionOverlay: 1
92 | m_LightingDataAsset: {fileID: 0}
93 | m_UseShadowmask: 1
94 | --- !u!196 &4
95 | NavMeshSettings:
96 | serializedVersion: 2
97 | m_ObjectHideFlags: 0
98 | m_BuildSettings:
99 | serializedVersion: 2
100 | agentTypeID: 0
101 | agentRadius: 0.5
102 | agentHeight: 2
103 | agentSlope: 45
104 | agentClimb: 0.4
105 | ledgeDropHeight: 0
106 | maxJumpAcrossDistance: 0
107 | minRegionArea: 2
108 | manualCellSize: 0
109 | cellSize: 0.16666667
110 | manualTileSize: 0
111 | tileSize: 256
112 | accuratePlacement: 0
113 | debug:
114 | m_Flags: 0
115 | m_NavMeshData: {fileID: 0}
116 | --- !u!1 &79645593
117 | GameObject:
118 | m_ObjectHideFlags: 0
119 | m_PrefabParentObject: {fileID: 0}
120 | m_PrefabInternal: {fileID: 0}
121 | serializedVersion: 5
122 | m_Component:
123 | - component: {fileID: 79645598}
124 | - component: {fileID: 79645597}
125 | - component: {fileID: 79645596}
126 | - component: {fileID: 79645595}
127 | - component: {fileID: 79645594}
128 | m_Layer: 0
129 | m_Name: wp2
130 | m_TagString: Untagged
131 | m_Icon: {fileID: 0}
132 | m_NavMeshLayer: 0
133 | m_StaticEditorFlags: 0
134 | m_IsActive: 1
135 | --- !u!114 &79645594
136 | MonoBehaviour:
137 | m_ObjectHideFlags: 0
138 | m_PrefabParentObject: {fileID: 0}
139 | m_PrefabInternal: {fileID: 0}
140 | m_GameObject: {fileID: 79645593}
141 | m_Enabled: 1
142 | m_EditorHideFlags: 0
143 | m_Script: {fileID: 11500000, guid: 55b1bdb9d4b2b0342b8fc84328b71c30, type: 3}
144 | m_Name:
145 | m_EditorClassIdentifier:
146 | --- !u!23 &79645595
147 | MeshRenderer:
148 | m_ObjectHideFlags: 0
149 | m_PrefabParentObject: {fileID: 0}
150 | m_PrefabInternal: {fileID: 0}
151 | m_GameObject: {fileID: 79645593}
152 | m_Enabled: 1
153 | m_CastShadows: 1
154 | m_ReceiveShadows: 1
155 | m_DynamicOccludee: 1
156 | m_MotionVectors: 1
157 | m_LightProbeUsage: 1
158 | m_ReflectionProbeUsage: 1
159 | m_Materials:
160 | - {fileID: 2100000, guid: 3aa0fa22682631942a3837e3d223b319, type: 2}
161 | m_StaticBatchInfo:
162 | firstSubMesh: 0
163 | subMeshCount: 0
164 | m_StaticBatchRoot: {fileID: 0}
165 | m_ProbeAnchor: {fileID: 0}
166 | m_LightProbeVolumeOverride: {fileID: 0}
167 | m_ScaleInLightmap: 1
168 | m_PreserveUVs: 1
169 | m_IgnoreNormalsForChartDetection: 0
170 | m_ImportantGI: 0
171 | m_StitchLightmapSeams: 0
172 | m_SelectedEditorRenderState: 3
173 | m_MinimumChartSize: 4
174 | m_AutoUVMaxDistance: 0.5
175 | m_AutoUVMaxAngle: 89
176 | m_LightmapParameters: {fileID: 0}
177 | m_SortingLayerID: 0
178 | m_SortingLayer: 0
179 | m_SortingOrder: 0
180 | --- !u!65 &79645596
181 | BoxCollider:
182 | m_ObjectHideFlags: 0
183 | m_PrefabParentObject: {fileID: 0}
184 | m_PrefabInternal: {fileID: 0}
185 | m_GameObject: {fileID: 79645593}
186 | m_Material: {fileID: 0}
187 | m_IsTrigger: 0
188 | m_Enabled: 1
189 | serializedVersion: 2
190 | m_Size: {x: 1, y: 1, z: 1}
191 | m_Center: {x: 0, y: 0, z: 0}
192 | --- !u!33 &79645597
193 | MeshFilter:
194 | m_ObjectHideFlags: 0
195 | m_PrefabParentObject: {fileID: 0}
196 | m_PrefabInternal: {fileID: 0}
197 | m_GameObject: {fileID: 79645593}
198 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
199 | --- !u!4 &79645598
200 | Transform:
201 | m_ObjectHideFlags: 0
202 | m_PrefabParentObject: {fileID: 0}
203 | m_PrefabInternal: {fileID: 0}
204 | m_GameObject: {fileID: 79645593}
205 | m_LocalRotation: {x: 0.19493176, y: 0.17110382, z: -0.034557614, w: 0.9651585}
206 | m_LocalPosition: {x: 0, y: 4.18, z: 0}
207 | m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
208 | m_Children: []
209 | m_Father: {fileID: 0}
210 | m_RootOrder: 4
211 | m_LocalEulerAnglesHint: {x: 22.837002, y: 20.106, z: 0}
212 | --- !u!1 &198375900
213 | GameObject:
214 | m_ObjectHideFlags: 0
215 | m_PrefabParentObject: {fileID: 0}
216 | m_PrefabInternal: {fileID: 0}
217 | serializedVersion: 5
218 | m_Component:
219 | - component: {fileID: 198375904}
220 | - component: {fileID: 198375903}
221 | - component: {fileID: 198375902}
222 | - component: {fileID: 198375901}
223 | - component: {fileID: 198375906}
224 | - component: {fileID: 198375905}
225 | m_Layer: 0
226 | m_Name: BehaviourSphere
227 | m_TagString: Untagged
228 | m_Icon: {fileID: 0}
229 | m_NavMeshLayer: 0
230 | m_StaticEditorFlags: 0
231 | m_IsActive: 1
232 | --- !u!23 &198375901
233 | MeshRenderer:
234 | m_ObjectHideFlags: 0
235 | m_PrefabParentObject: {fileID: 0}
236 | m_PrefabInternal: {fileID: 0}
237 | m_GameObject: {fileID: 198375900}
238 | m_Enabled: 1
239 | m_CastShadows: 1
240 | m_ReceiveShadows: 1
241 | m_DynamicOccludee: 1
242 | m_MotionVectors: 1
243 | m_LightProbeUsage: 1
244 | m_ReflectionProbeUsage: 1
245 | m_Materials:
246 | - {fileID: 2100000, guid: f56bc685b518fd942a38e670388db070, type: 2}
247 | m_StaticBatchInfo:
248 | firstSubMesh: 0
249 | subMeshCount: 0
250 | m_StaticBatchRoot: {fileID: 0}
251 | m_ProbeAnchor: {fileID: 0}
252 | m_LightProbeVolumeOverride: {fileID: 0}
253 | m_ScaleInLightmap: 1
254 | m_PreserveUVs: 1
255 | m_IgnoreNormalsForChartDetection: 0
256 | m_ImportantGI: 0
257 | m_StitchLightmapSeams: 0
258 | m_SelectedEditorRenderState: 3
259 | m_MinimumChartSize: 4
260 | m_AutoUVMaxDistance: 0.5
261 | m_AutoUVMaxAngle: 89
262 | m_LightmapParameters: {fileID: 0}
263 | m_SortingLayerID: 0
264 | m_SortingLayer: 0
265 | m_SortingOrder: 0
266 | --- !u!135 &198375902
267 | SphereCollider:
268 | m_ObjectHideFlags: 0
269 | m_PrefabParentObject: {fileID: 0}
270 | m_PrefabInternal: {fileID: 0}
271 | m_GameObject: {fileID: 198375900}
272 | m_Material: {fileID: 0}
273 | m_IsTrigger: 0
274 | m_Enabled: 1
275 | serializedVersion: 2
276 | m_Radius: 0.5
277 | m_Center: {x: 0, y: 0, z: 0}
278 | --- !u!33 &198375903
279 | MeshFilter:
280 | m_ObjectHideFlags: 0
281 | m_PrefabParentObject: {fileID: 0}
282 | m_PrefabInternal: {fileID: 0}
283 | m_GameObject: {fileID: 198375900}
284 | m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
285 | --- !u!4 &198375904
286 | Transform:
287 | m_ObjectHideFlags: 0
288 | m_PrefabParentObject: {fileID: 0}
289 | m_PrefabInternal: {fileID: 0}
290 | m_GameObject: {fileID: 198375900}
291 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
292 | m_LocalPosition: {x: -2.53, y: 0, z: 0}
293 | m_LocalScale: {x: 1, y: 1, z: 1}
294 | m_Children: []
295 | m_Father: {fileID: 0}
296 | m_RootOrder: 1
297 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
298 | --- !u!114 &198375905
299 | MonoBehaviour:
300 | m_ObjectHideFlags: 0
301 | m_PrefabParentObject: {fileID: 0}
302 | m_PrefabInternal: {fileID: 0}
303 | m_GameObject: {fileID: 198375900}
304 | m_Enabled: 1
305 | m_EditorHideFlags: 0
306 | m_Script: {fileID: 11500000, guid: 3f9d7d6484b685c4aaf20be9b7610268, type: 3}
307 | m_Name:
308 | m_EditorClassIdentifier:
309 | --- !u!114 &198375906
310 | MonoBehaviour:
311 | m_ObjectHideFlags: 0
312 | m_PrefabParentObject: {fileID: 0}
313 | m_PrefabInternal: {fileID: 0}
314 | m_GameObject: {fileID: 198375900}
315 | m_Enabled: 1
316 | m_EditorHideFlags: 0
317 | m_Script: {fileID: 11500000, guid: 0a42377429ca0704eadf2a777daf71e4, type: 3}
318 | m_Name:
319 | m_EditorClassIdentifier:
320 | waypoints:
321 | - {fileID: 1483189095}
322 | - {fileID: 79645594}
323 | - {fileID: 1967686624}
324 | --- !u!1 &1192597011
325 | GameObject:
326 | m_ObjectHideFlags: 0
327 | m_PrefabParentObject: {fileID: 0}
328 | m_PrefabInternal: {fileID: 0}
329 | serializedVersion: 5
330 | m_Component:
331 | - component: {fileID: 1192597013}
332 | - component: {fileID: 1192597012}
333 | m_Layer: 0
334 | m_Name: Point light
335 | m_TagString: Untagged
336 | m_Icon: {fileID: 0}
337 | m_NavMeshLayer: 0
338 | m_StaticEditorFlags: 0
339 | m_IsActive: 1
340 | --- !u!108 &1192597012
341 | Light:
342 | m_ObjectHideFlags: 0
343 | m_PrefabParentObject: {fileID: 0}
344 | m_PrefabInternal: {fileID: 0}
345 | m_GameObject: {fileID: 1192597011}
346 | m_Enabled: 1
347 | serializedVersion: 8
348 | m_Type: 2
349 | m_Color: {r: 1, g: 1, b: 1, a: 1}
350 | m_Intensity: 1
351 | m_Range: 10
352 | m_SpotAngle: 30
353 | m_CookieSize: 10
354 | m_Shadows:
355 | m_Type: 0
356 | m_Resolution: -1
357 | m_CustomResolution: -1
358 | m_Strength: 1
359 | m_Bias: 0.05
360 | m_NormalBias: 0.4
361 | m_NearPlane: 0.2
362 | m_Cookie: {fileID: 0}
363 | m_DrawHalo: 0
364 | m_Flare: {fileID: 0}
365 | m_RenderMode: 0
366 | m_CullingMask:
367 | serializedVersion: 2
368 | m_Bits: 4294967295
369 | m_Lightmapping: 4
370 | m_AreaSize: {x: 1, y: 1}
371 | m_BounceIntensity: 1
372 | m_ColorTemperature: 6570
373 | m_UseColorTemperature: 0
374 | m_ShadowRadius: 0
375 | m_ShadowAngle: 0
376 | --- !u!4 &1192597013
377 | Transform:
378 | m_ObjectHideFlags: 0
379 | m_PrefabParentObject: {fileID: 0}
380 | m_PrefabInternal: {fileID: 0}
381 | m_GameObject: {fileID: 1192597011}
382 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
383 | m_LocalPosition: {x: 0, y: 0, z: -1.97}
384 | m_LocalScale: {x: 1, y: 1, z: 1}
385 | m_Children: []
386 | m_Father: {fileID: 0}
387 | m_RootOrder: 2
388 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
389 | --- !u!1 &1458245724
390 | GameObject:
391 | m_ObjectHideFlags: 0
392 | m_PrefabParentObject: {fileID: 0}
393 | m_PrefabInternal: {fileID: 0}
394 | serializedVersion: 5
395 | m_Component:
396 | - component: {fileID: 1458245728}
397 | - component: {fileID: 1458245727}
398 | - component: {fileID: 1458245726}
399 | - component: {fileID: 1458245725}
400 | m_Layer: 0
401 | m_Name: Main Camera
402 | m_TagString: MainCamera
403 | m_Icon: {fileID: 0}
404 | m_NavMeshLayer: 0
405 | m_StaticEditorFlags: 0
406 | m_IsActive: 1
407 | --- !u!81 &1458245725
408 | AudioListener:
409 | m_ObjectHideFlags: 0
410 | m_PrefabParentObject: {fileID: 0}
411 | m_PrefabInternal: {fileID: 0}
412 | m_GameObject: {fileID: 1458245724}
413 | m_Enabled: 1
414 | --- !u!124 &1458245726
415 | Behaviour:
416 | m_ObjectHideFlags: 0
417 | m_PrefabParentObject: {fileID: 0}
418 | m_PrefabInternal: {fileID: 0}
419 | m_GameObject: {fileID: 1458245724}
420 | m_Enabled: 1
421 | --- !u!20 &1458245727
422 | Camera:
423 | m_ObjectHideFlags: 0
424 | m_PrefabParentObject: {fileID: 0}
425 | m_PrefabInternal: {fileID: 0}
426 | m_GameObject: {fileID: 1458245724}
427 | m_Enabled: 1
428 | serializedVersion: 2
429 | m_ClearFlags: 2
430 | m_BackGroundColor: {r: 0.6002864, g: 0.39987025, b: 0.63235295, a: 0}
431 | m_NormalizedViewPortRect:
432 | serializedVersion: 2
433 | x: 0
434 | y: 0
435 | width: 1
436 | height: 1
437 | near clip plane: 0.3
438 | far clip plane: 1000
439 | field of view: 60
440 | orthographic: 0
441 | orthographic size: 5
442 | m_Depth: -1
443 | m_CullingMask:
444 | serializedVersion: 2
445 | m_Bits: 4294967295
446 | m_RenderingPath: -1
447 | m_TargetTexture: {fileID: 0}
448 | m_TargetDisplay: 0
449 | m_TargetEye: 3
450 | m_HDR: 1
451 | m_AllowMSAA: 1
452 | m_AllowDynamicResolution: 0
453 | m_ForceIntoRT: 0
454 | m_OcclusionCulling: 1
455 | m_StereoConvergence: 10
456 | m_StereoSeparation: 0.022
457 | --- !u!4 &1458245728
458 | Transform:
459 | m_ObjectHideFlags: 0
460 | m_PrefabParentObject: {fileID: 0}
461 | m_PrefabInternal: {fileID: 0}
462 | m_GameObject: {fileID: 1458245724}
463 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
464 | m_LocalPosition: {x: 0, y: 0, z: -10}
465 | m_LocalScale: {x: 1, y: 1, z: 1}
466 | m_Children: []
467 | m_Father: {fileID: 0}
468 | m_RootOrder: 0
469 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
470 | --- !u!1 &1483189094
471 | GameObject:
472 | m_ObjectHideFlags: 0
473 | m_PrefabParentObject: {fileID: 0}
474 | m_PrefabInternal: {fileID: 0}
475 | serializedVersion: 5
476 | m_Component:
477 | - component: {fileID: 1483189099}
478 | - component: {fileID: 1483189098}
479 | - component: {fileID: 1483189097}
480 | - component: {fileID: 1483189096}
481 | - component: {fileID: 1483189095}
482 | m_Layer: 0
483 | m_Name: wp1
484 | m_TagString: Untagged
485 | m_Icon: {fileID: 0}
486 | m_NavMeshLayer: 0
487 | m_StaticEditorFlags: 0
488 | m_IsActive: 1
489 | --- !u!114 &1483189095
490 | MonoBehaviour:
491 | m_ObjectHideFlags: 0
492 | m_PrefabParentObject: {fileID: 0}
493 | m_PrefabInternal: {fileID: 0}
494 | m_GameObject: {fileID: 1483189094}
495 | m_Enabled: 1
496 | m_EditorHideFlags: 0
497 | m_Script: {fileID: 11500000, guid: 55b1bdb9d4b2b0342b8fc84328b71c30, type: 3}
498 | m_Name:
499 | m_EditorClassIdentifier:
500 | --- !u!23 &1483189096
501 | MeshRenderer:
502 | m_ObjectHideFlags: 0
503 | m_PrefabParentObject: {fileID: 0}
504 | m_PrefabInternal: {fileID: 0}
505 | m_GameObject: {fileID: 1483189094}
506 | m_Enabled: 1
507 | m_CastShadows: 1
508 | m_ReceiveShadows: 1
509 | m_DynamicOccludee: 1
510 | m_MotionVectors: 1
511 | m_LightProbeUsage: 1
512 | m_ReflectionProbeUsage: 1
513 | m_Materials:
514 | - {fileID: 2100000, guid: 3aa0fa22682631942a3837e3d223b319, type: 2}
515 | m_StaticBatchInfo:
516 | firstSubMesh: 0
517 | subMeshCount: 0
518 | m_StaticBatchRoot: {fileID: 0}
519 | m_ProbeAnchor: {fileID: 0}
520 | m_LightProbeVolumeOverride: {fileID: 0}
521 | m_ScaleInLightmap: 1
522 | m_PreserveUVs: 1
523 | m_IgnoreNormalsForChartDetection: 0
524 | m_ImportantGI: 0
525 | m_StitchLightmapSeams: 0
526 | m_SelectedEditorRenderState: 3
527 | m_MinimumChartSize: 4
528 | m_AutoUVMaxDistance: 0.5
529 | m_AutoUVMaxAngle: 89
530 | m_LightmapParameters: {fileID: 0}
531 | m_SortingLayerID: 0
532 | m_SortingLayer: 0
533 | m_SortingOrder: 0
534 | --- !u!65 &1483189097
535 | BoxCollider:
536 | m_ObjectHideFlags: 0
537 | m_PrefabParentObject: {fileID: 0}
538 | m_PrefabInternal: {fileID: 0}
539 | m_GameObject: {fileID: 1483189094}
540 | m_Material: {fileID: 0}
541 | m_IsTrigger: 0
542 | m_Enabled: 1
543 | serializedVersion: 2
544 | m_Size: {x: 1, y: 1, z: 1}
545 | m_Center: {x: 0, y: 0, z: 0}
546 | --- !u!33 &1483189098
547 | MeshFilter:
548 | m_ObjectHideFlags: 0
549 | m_PrefabParentObject: {fileID: 0}
550 | m_PrefabInternal: {fileID: 0}
551 | m_GameObject: {fileID: 1483189094}
552 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
553 | --- !u!4 &1483189099
554 | Transform:
555 | m_ObjectHideFlags: 0
556 | m_PrefabParentObject: {fileID: 0}
557 | m_PrefabInternal: {fileID: 0}
558 | m_GameObject: {fileID: 1483189094}
559 | m_LocalRotation: {x: -0.24435875, y: -0.2510821, z: -0.25440866, w: 0.90140045}
560 | m_LocalPosition: {x: 5.1, y: -1.42, z: 0}
561 | m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
562 | m_Children: []
563 | m_Father: {fileID: 0}
564 | m_RootOrder: 3
565 | m_LocalEulerAnglesHint: {x: -34.631, y: -23.516, z: -24.096}
566 | --- !u!1 &1967686623
567 | GameObject:
568 | m_ObjectHideFlags: 0
569 | m_PrefabParentObject: {fileID: 0}
570 | m_PrefabInternal: {fileID: 0}
571 | serializedVersion: 5
572 | m_Component:
573 | - component: {fileID: 1967686628}
574 | - component: {fileID: 1967686627}
575 | - component: {fileID: 1967686626}
576 | - component: {fileID: 1967686625}
577 | - component: {fileID: 1967686624}
578 | m_Layer: 0
579 | m_Name: wp3
580 | m_TagString: Untagged
581 | m_Icon: {fileID: 0}
582 | m_NavMeshLayer: 0
583 | m_StaticEditorFlags: 0
584 | m_IsActive: 1
585 | --- !u!114 &1967686624
586 | MonoBehaviour:
587 | m_ObjectHideFlags: 0
588 | m_PrefabParentObject: {fileID: 0}
589 | m_PrefabInternal: {fileID: 0}
590 | m_GameObject: {fileID: 1967686623}
591 | m_Enabled: 1
592 | m_EditorHideFlags: 0
593 | m_Script: {fileID: 11500000, guid: 55b1bdb9d4b2b0342b8fc84328b71c30, type: 3}
594 | m_Name:
595 | m_EditorClassIdentifier:
596 | --- !u!23 &1967686625
597 | MeshRenderer:
598 | m_ObjectHideFlags: 0
599 | m_PrefabParentObject: {fileID: 0}
600 | m_PrefabInternal: {fileID: 0}
601 | m_GameObject: {fileID: 1967686623}
602 | m_Enabled: 1
603 | m_CastShadows: 1
604 | m_ReceiveShadows: 1
605 | m_DynamicOccludee: 1
606 | m_MotionVectors: 1
607 | m_LightProbeUsage: 1
608 | m_ReflectionProbeUsage: 1
609 | m_Materials:
610 | - {fileID: 2100000, guid: 3aa0fa22682631942a3837e3d223b319, type: 2}
611 | m_StaticBatchInfo:
612 | firstSubMesh: 0
613 | subMeshCount: 0
614 | m_StaticBatchRoot: {fileID: 0}
615 | m_ProbeAnchor: {fileID: 0}
616 | m_LightProbeVolumeOverride: {fileID: 0}
617 | m_ScaleInLightmap: 1
618 | m_PreserveUVs: 1
619 | m_IgnoreNormalsForChartDetection: 0
620 | m_ImportantGI: 0
621 | m_StitchLightmapSeams: 0
622 | m_SelectedEditorRenderState: 3
623 | m_MinimumChartSize: 4
624 | m_AutoUVMaxDistance: 0.5
625 | m_AutoUVMaxAngle: 89
626 | m_LightmapParameters: {fileID: 0}
627 | m_SortingLayerID: 0
628 | m_SortingLayer: 0
629 | m_SortingOrder: 0
630 | --- !u!65 &1967686626
631 | BoxCollider:
632 | m_ObjectHideFlags: 0
633 | m_PrefabParentObject: {fileID: 0}
634 | m_PrefabInternal: {fileID: 0}
635 | m_GameObject: {fileID: 1967686623}
636 | m_Material: {fileID: 0}
637 | m_IsTrigger: 0
638 | m_Enabled: 1
639 | serializedVersion: 2
640 | m_Size: {x: 1, y: 1, z: 1}
641 | m_Center: {x: 0, y: 0, z: 0}
642 | --- !u!33 &1967686627
643 | MeshFilter:
644 | m_ObjectHideFlags: 0
645 | m_PrefabParentObject: {fileID: 0}
646 | m_PrefabInternal: {fileID: 0}
647 | m_GameObject: {fileID: 1967686623}
648 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
649 | --- !u!4 &1967686628
650 | Transform:
651 | m_ObjectHideFlags: 0
652 | m_PrefabParentObject: {fileID: 0}
653 | m_PrefabInternal: {fileID: 0}
654 | m_GameObject: {fileID: 1967686623}
655 | m_LocalRotation: {x: 0.47066876, y: 0.47551182, z: 0.10673601, w: 0.7355045}
656 | m_LocalPosition: {x: -4.34, y: -3.13, z: 0}
657 | m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
658 | m_Children: []
659 | m_Father: {fileID: 0}
660 | m_RootOrder: 5
661 | m_LocalEulerAnglesHint: {x: 36.217003, y: 82.54201, z: 48.541004}
662 |
--------------------------------------------------------------------------------