Add wandering behaviour

This commit is contained in:
Jens Pitkänen 2019-08-04 16:44:44 +03:00
parent 834d2fe6d2
commit 4db20c6ea5
10 changed files with 284 additions and 27 deletions

View File

@ -184,6 +184,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f7e23822f429fcc46a8fd9163e68f332, type: 3}
m_Name:
m_EditorClassIdentifier:
CurrentStatus:
Target: {fileID: 0}
CloseEnoughRadius: 1
--- !u!114 &162528940
@ -230,6 +231,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
MoveSpeed: 2
BehaviourTree: {fileID: 162528941}
CurrentBehavior: Nothing
--- !u!61 &162528943
BoxCollider2D:
m_ObjectHideFlags: 0
@ -285,8 +287,8 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 162528936}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 4, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 4.19, y: 1.47, z: 0}
m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
m_Children:
- {fileID: 1237792229}
m_Father: {fileID: 0}
@ -1303,12 +1305,12 @@ PrefabInstance:
propertyPath: MoveSpeed
value: 5
objectReference: {fileID: 0}
- target: {fileID: 8489029732241002784, guid: 14a47f86f9e45da45863a81716f2378b,
- target: {fileID: 8489029732599905344, guid: 14a47f86f9e45da45863a81716f2378b,
type: 3}
propertyPath: m_SortingLayer
value: 3
objectReference: {fileID: 0}
- target: {fileID: 8489029732599905344, guid: 14a47f86f9e45da45863a81716f2378b,
- target: {fileID: 8489029732241002784, guid: 14a47f86f9e45da45863a81716f2378b,
type: 3}
propertyPath: m_SortingLayer
value: 3
@ -1614,6 +1616,15 @@ Tilemap:
m_TileFlags: 1
m_ColliderType: 1
- first: {x: -2, y: 0, z: 0}
second:
m_TileIndex: 11
m_TileSpriteIndex: 11
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: -1, y: 0, z: 0}
second:
m_TileIndex: 7
m_TileSpriteIndex: 7
@ -1622,6 +1633,69 @@ Tilemap:
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 0, y: 0, z: 0}
second:
m_TileIndex: 7
m_TileSpriteIndex: 7
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 1, y: 0, z: 0}
second:
m_TileIndex: 7
m_TileSpriteIndex: 7
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 2, y: 0, z: 0}
second:
m_TileIndex: 7
m_TileSpriteIndex: 7
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 3, y: 0, z: 0}
second:
m_TileIndex: 7
m_TileSpriteIndex: 7
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 4, y: 0, z: 0}
second:
m_TileIndex: 7
m_TileSpriteIndex: 7
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 5, y: 0, z: 0}
second:
m_TileIndex: 7
m_TileSpriteIndex: 7
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 6, y: 0, z: 0}
second:
m_TileIndex: 14
m_TileSpriteIndex: 14
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: -6, y: 1, z: 0}
second:
m_TileIndex: 10
@ -1640,6 +1714,24 @@ Tilemap:
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: -2, y: 1, z: 0}
second:
m_TileIndex: 10
m_TileSpriteIndex: 10
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: 6, y: 1, z: 0}
second:
m_TileIndex: 13
m_TileSpriteIndex: 13
m_TileMatrixIndex: 0
m_TileColorIndex: 8
m_ObjectToInstantiate: {fileID: 0}
m_TileFlags: 1
m_ColliderType: 1
- first: {x: -6, y: 2, z: 0}
second:
m_TileIndex: 9
@ -1755,21 +1847,21 @@ Tilemap:
m_Data: {fileID: 0}
- m_RefCount: 0
m_Data: {fileID: 0}
- m_RefCount: 9
- m_RefCount: 15
m_Data: {fileID: 11400000, guid: 2004c99dc125dd542aafd24f4ad842f4, type: 2}
- m_RefCount: 0
m_Data: {fileID: 0}
- m_RefCount: 1
m_Data: {fileID: 11400000, guid: d71c3f314fe54f141b9df7c5699b66ab, type: 2}
- m_RefCount: 3
- m_RefCount: 4
m_Data: {fileID: 11400000, guid: 3a266bd53dfebcf479f723737979e62d, type: 2}
- m_RefCount: 2
- m_RefCount: 3
m_Data: {fileID: 11400000, guid: bf9ccb7cbc24ca346944cfd6efb15bf6, type: 2}
- m_RefCount: 1
m_Data: {fileID: 11400000, guid: b673d03227bc8f74eab4645216e9d2a4, type: 2}
- m_RefCount: 3
- m_RefCount: 4
m_Data: {fileID: 11400000, guid: 607b380a0644eb9438d6f72c3c8434c5, type: 2}
- m_RefCount: 2
- m_RefCount: 3
m_Data: {fileID: 11400000, guid: 4bbf78a58bd67f246927f19ce84be3fd, type: 2}
m_TileSpriteArray:
- m_RefCount: 0
@ -1786,7 +1878,7 @@ Tilemap:
m_Data: {fileID: 0}
- m_RefCount: 0
m_Data: {fileID: 0}
- m_RefCount: 9
- m_RefCount: 15
m_Data: {fileID: 6408231970667830406, guid: 3b5f43ce65db7e74f9d3a906dfc2c460,
type: 3}
- m_RefCount: 0
@ -1794,22 +1886,22 @@ Tilemap:
- m_RefCount: 1
m_Data: {fileID: 5441223297315994465, guid: 3b5f43ce65db7e74f9d3a906dfc2c460,
type: 3}
- m_RefCount: 3
- m_RefCount: 4
m_Data: {fileID: -8025435653959805260, guid: 3b5f43ce65db7e74f9d3a906dfc2c460,
type: 3}
- m_RefCount: 2
- m_RefCount: 3
m_Data: {fileID: -7869403223043187030, guid: 3b5f43ce65db7e74f9d3a906dfc2c460,
type: 3}
- m_RefCount: 1
m_Data: {fileID: -6108889420429456849, guid: 3b5f43ce65db7e74f9d3a906dfc2c460,
type: 3}
- m_RefCount: 3
- m_RefCount: 4
m_Data: {fileID: -6315978382755026507, guid: 3b5f43ce65db7e74f9d3a906dfc2c460,
type: 3}
- m_RefCount: 2
- m_RefCount: 3
m_Data: {fileID: 511961965738296472, guid: 3b5f43ce65db7e74f9d3a906dfc2c460, type: 3}
m_TileMatrixArray:
- m_RefCount: 21
- m_RefCount: 31
m_Data:
e00: 1
e01: 0
@ -1844,7 +1936,7 @@ Tilemap:
m_Data: {r: 0, g: 0, b: 0, a: 0}
- m_RefCount: 0
m_Data: {r: 0, g: 0, b: 0, a: 0}
- m_RefCount: 21
- m_RefCount: 31
m_Data: {r: 1, g: 1, b: 1, a: 1}
m_AnimationFrameRate: 1
m_Color: {r: 1, g: 1, b: 1, a: 1}
@ -1923,8 +2015,8 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 867100008}
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_LocalPosition: {x: 0.19, y: 1.47, z: 0}
m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
m_Children:
- {fileID: 1000260803}
m_Father: {fileID: 0}
@ -1944,6 +2036,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
MoveSpeed: 2
BehaviourTree: {fileID: 867100012}
CurrentBehavior: Nothing
--- !u!50 &867100011
Rigidbody2D:
serializedVersion: 4
@ -2046,6 +2139,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f7e23822f429fcc46a8fd9163e68f332, type: 3}
m_Name:
m_EditorClassIdentifier:
CurrentStatus:
Target: {fileID: 0}
CloseEnoughRadius: 1
--- !u!114 &867100017
@ -2091,8 +2185,12 @@ GameObject:
- component: {fileID: 895097235}
- component: {fileID: 895097234}
- component: {fileID: 895097233}
- component: {fileID: 895097240}
- component: {fileID: 895097239}
- component: {fileID: 895097238}
- component: {fileID: 895097237}
m_Layer: 0
m_Name: Enemy (2)
m_Name: Enemy (Default Melee)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -2154,8 +2252,8 @@ Rigidbody2D:
m_UseFullKinematicContacts: 1
m_UseAutoMass: 0
m_Mass: 5
m_LinearDrag: 2
m_AngularDrag: 2
m_LinearDrag: 8
m_AngularDrag: 0
m_GravityScale: 1
m_Material: {fileID: 0}
m_Interpolate: 1
@ -2170,13 +2268,75 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 895097232}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -3.43, y: -0.6, z: 0}
m_LocalPosition: {x: -0.43, y: -2.53, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 490037238}
m_Father: {fileID: 0}
m_RootOrder: 6
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &895097237
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 895097232}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bf838f73fb74f0046a5b6a86994c54ed, type: 3}
m_Name:
m_EditorClassIdentifier:
CurrentStatus:
WalkingDistance: 2
MinWalkingDistance: 1
SubjectRadius: 0.7
StopLength: 2
--- !u!114 &895097238
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 895097232}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 163f55033e69e2e4282c151e1a806bc6, type: 3}
m_Name:
m_EditorClassIdentifier:
Behaviours:
- {fileID: 895097237}
--- !u!114 &895097239
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 895097232}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbf2158cd27572e4599b4c813f555fd8, type: 3}
m_Name:
m_EditorClassIdentifier:
Trigger: {fileID: 0}
TriggeredNodes: []
NotTriggeredNodes:
- {fileID: 895097238}
--- !u!114 &895097240
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 895097232}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 978bec54408eb8f42a36fd68d7447f5a, type: 3}
m_Name:
m_EditorClassIdentifier:
MoveSpeed: 1
BehaviourTree: {fileID: 895097239}
CurrentBehavior: Nothing
--- !u!1 &963194225
GameObject:
m_ObjectHideFlags: 0

View File

@ -1,7 +1,9 @@
using UnityEngine;
namespace Saltosion.OneWeapon.AI {
public abstract class Behaviour : MonoBehaviour {
public abstract class AIBehaviour : MonoBehaviour {
public string CurrentStatus = "";
/* Returns whether or not Execute() should be called this frame */
public abstract bool CanBehave(Enemy subject);
/* Returns whether or not this was a blocking behaviour, ie. should the behaviour processing be stopped here */

View File

@ -8,22 +8,30 @@ namespace Saltosion.OneWeapon.AI {
public BehaviourNode[] TriggeredNodes;
public BehaviourNode[] NotTriggeredNodes;
private String MostRecentExecution;
/* Returns true if any action was taken. */
public override bool Execute(Enemy subject) {
if (Trigger.IsTriggered(subject)) {
if (Trigger != null && Trigger.IsTriggered(subject)) {
foreach (BehaviourNode Node in TriggeredNodes) {
if (Node.Execute(subject)) {
MostRecentExecution = Node.GetExecutedName();
return true;
}
}
} else {
foreach (BehaviourNode Node in NotTriggeredNodes) {
if (Node.Execute(subject)) {
MostRecentExecution = Node.GetExecutedName();
return true;
}
}
}
return false;
}
public override string GetExecutedName() {
return MostRecentExecution;
}
}
}

View File

@ -4,14 +4,18 @@ using UnityEngine;
namespace Saltosion.OneWeapon.AI {
[Serializable]
public class BehaviourLeaf : BehaviourNode {
public Behaviour[] Behaviours;
public AIBehaviour[] Behaviours;
public bool IsLeaf { get { return Behaviours.Length > 0; } }
private string ExecutedBehaviours = "";
/* Returns true if any action was taken. */
public override bool Execute(Enemy subject) {
bool Acted = false;
foreach (Behaviour Behaviour in Behaviours) {
ExecutedBehaviours = "";
foreach (AIBehaviour Behaviour in Behaviours) {
if (Behaviour.CanBehave(subject)) {
ExecutedBehaviours += Behaviour.GetType().Name + ":" + Behaviour.CurrentStatus + ", ";
if (Behaviour.Execute(subject)) {
return true;
} else {
@ -21,5 +25,9 @@ namespace Saltosion.OneWeapon.AI {
}
return Acted;
}
public override string GetExecutedName() {
return ExecutedBehaviours;
}
}
}

View File

@ -6,5 +6,7 @@ namespace Saltosion.OneWeapon.AI {
public abstract class BehaviourNode : MonoBehaviour {
/* Returns true if any action was taken. */
public abstract bool Execute(Enemy subject);
public abstract string GetExecutedName();
}
}

View File

@ -1,7 +1,7 @@
using UnityEngine;
namespace Saltosion.OneWeapon.AI.Behaviours {
public class Follow : Behaviour {
public class Follow : AIBehaviour {
public Transform Target;
public float CloseEnoughRadius;

View File

@ -0,0 +1,60 @@
using UnityEngine;
namespace Saltosion.OneWeapon.AI.Behaviours {
public class Wander : AIBehaviour {
public float WalkingDistance;
public float MinWalkingDistance;
public float SubjectRadius;
public float StopLength;
private Vector2 Target;
private float StopTime;
private bool Stopped = true;
private void Start() {
StopTime = Time.time;
}
public override bool CanBehave(Enemy subject) {
return true;
}
public override bool Execute(Enemy subject) {
Vector2 SubjectPosition = (Vector2)subject.transform.position;
if ((Target - SubjectPosition).magnitude > SubjectRadius) {
subject.StartMovingTo(Target);
CurrentStatus = "Move";
Stopped = false;
return true;
} else if (!Stopped) {
Stopped = true;
StopTime = Time.time;
Target = SubjectPosition;
} else if (Time.time - StopTime > StopLength) {
// The AI is near the target, and has waited for StopTime.
// Now we pick a new target.
CurrentStatus = "Search";
int i = 0;
while ((Target - SubjectPosition).magnitude <= SubjectRadius) {
i++;
if (i > 100) {
Debug.LogWarning($"Wander behaviour took over 100 tries to find a wander position, '{subject.name}' is stuck!");
break;
}
float Distance = MinWalkingDistance + (WalkingDistance - MinWalkingDistance) * Random.value;
float Direction = Random.value * Mathf.PI * 2f;
Vector2 Delta = new Vector2(Mathf.Cos(Direction), Mathf.Sin(Direction)) * Distance;
RaycastHit2D Hit = Physics2D.Raycast(SubjectPosition + Delta.normalized * SubjectRadius, Delta.normalized, Distance);
if (Hit.rigidbody == null) {
Target = SubjectPosition + Delta;
}
}
} else {
CurrentStatus = "Stop";
}
subject.StopMoving();
return false;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf838f73fb74f0046a5b6a86994c54ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -6,6 +6,8 @@ namespace Saltosion.OneWeapon {
public class Enemy : MonoBehaviour {
public float MoveSpeed;
public BehaviourNode BehaviourTree;
[Space(20)]
public string CurrentBehavior = "Nothing";
private Rigidbody2D Body;
private bool MovingToTarget = false;
@ -17,6 +19,7 @@ namespace Saltosion.OneWeapon {
private void Update() {
BehaviourTree.Execute(this);
CurrentBehavior = BehaviourTree.GetExecutedName();
}
private void FixedUpdate() {

View File

@ -35,6 +35,9 @@ GraphicsSettings:
- {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: []
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
type: 0}