From 7003262a5d6ddde17a87b6a711ce9266b273338a Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 25 Nov 2022 16:12:58 +0800 Subject: [PATCH] Fixed AI even after scene change -More reliance on the blackboard for keeping variables among a tree's nodes -Half extents of the AI fixed --- Assets/Scenes/MainGameWithAIFixed.shade | 2 +- .../BehaviourTree/Core/BehaviourTree.cs | 11 +++- .../AIBehaviour/Implemented/Homeowner1.cs | 54 +++++++++++++++-- .../Implemented/LeafNodes/LeafAttack.cs | 31 +++++++--- .../Implemented/LeafNodes/LeafChase.cs | 59 +++++++++++++------ .../Implemented/LeafNodes/LeafPatrol.cs | 39 +++++++----- .../Implemented/LeafNodes/LeafSearch.cs | 36 +++++++---- 7 files changed, 172 insertions(+), 60 deletions(-) diff --git a/Assets/Scenes/MainGameWithAIFixed.shade b/Assets/Scenes/MainGameWithAIFixed.shade index 2ec3155e..4a987708 100644 --- a/Assets/Scenes/MainGameWithAIFixed.shade +++ b/Assets/Scenes/MainGameWithAIFixed.shade @@ -8665,7 +8665,7 @@ Colliders: - Is Trigger: false Type: Box - Half Extents: {x: 1, y: 1.79999995, z: 0.400000006} + Half Extents: {x: 0.200000003, y: 0.899999976, z: 0.200000003} Friction: 0.400000006 Bounciness: 0 Density: 1 diff --git a/Assets/Scripts/AIBehaviour/BehaviourTree/Core/BehaviourTree.cs b/Assets/Scripts/AIBehaviour/BehaviourTree/Core/BehaviourTree.cs index 404e3df8..cdced78e 100644 --- a/Assets/Scripts/AIBehaviour/BehaviourTree/Core/BehaviourTree.cs +++ b/Assets/Scripts/AIBehaviour/BehaviourTree/Core/BehaviourTree.cs @@ -66,9 +66,16 @@ namespace SHADE_Scripting.AIBehaviour.BehaviourTree //Getters and setters for the blackboard public object GetData(string key) { + //Debug.Log("Getting Data " + key); object outData = null; - if (blackboard.TryGetValue(key, out outData)) return outData; - else return outData; + if (blackboard.TryGetValue(key, out outData)) + { + return outData; + } + else + { + return outData; + } } public void SetData(string key, object data) { diff --git a/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs b/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs index 8ebd0537..67c1034c 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs @@ -84,17 +84,56 @@ public partial class Homeowner1 : BehaviourTree _events = new Homeowner1Events(this); events.Initialise(); - //Initialise the waypoints here - if (waypointsPool) + //(25 Nov) DO NOT Initialise the data here + /*if (waypointsPool) { waypoints = (List)waypointsPool.GetChildren(); SetData("waypoints", waypoints); } + SetData("transform", GetComponent()); + SetData("rigidBody", GetComponent()); + SetData("eyeOffset", eyeOffset); + SetData("sightDistance", sightDistance); + SetData("patrolSpeed", patrolSpeed); + SetData("chaseSpeed", chaseSpeed); + SetData("turningSpeed", turningSpeed); + SetData("distanceToCapture", distanceToCapture); + SetData("baseCaptureTime", captureTime);*/ } //Called every tick protected override void Tick() { + Debug.Log("Ticking"); + //Update data + if (GetData("waypoints") == null) + { + if (waypointsPool) + SetData("waypoints", (List)waypointsPool.GetChildren()); + + List wpTemp = (List)GetData("waypoints"); + Debug.Log(wpTemp.Count.ToString()); + } + if (GetData("transform") == null) + SetData("transform", GetComponent()); + if (GetData("rigidBody") == null) + SetData("rigidBody", GetComponent()); + if (GetData("eyeOffset") == null || (Vector3)GetData("eyeOffset") != eyeOffset) + SetData("eyeOffset", eyeOffset); + if (GetData("sightDistance") == null || (float)GetData("sightDistance") != sightDistance) + SetData("sightDistance", sightDistance); + if (GetData("patrolSpeed") == null || (float)GetData("patrolSpeed") != patrolSpeed) + SetData("patrolSpeed", patrolSpeed); + if (GetData("chaseSpeed") == null || (float)GetData("chaseSpeed") != chaseSpeed) + SetData("chaseSpeed", chaseSpeed); + if (GetData("turningSpeed") == null || (float)GetData("turningSpeed") != turningSpeed) + SetData("turningSpeed", turningSpeed); + if (GetData("distanceToCapture") == null || (float)GetData("distanceToCapture") != distanceToCapture) + SetData("distanceToCapture", distanceToCapture); + if (GetData("baseCaptureTime") == null || (float)GetData("baseCaptureTime") != captureTime) + SetData("baseCaptureTime", captureTime); + + events.Tick(); //Footsteps SFX, move them somewhere else soon @@ -106,6 +145,7 @@ public partial class Homeowner1 : BehaviourTree Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_footsteps"); footstepTimeRemaining = footstepSFXIntervalMultiplier; } + Debug.Log("Ticked"); } //Define the behaviour tree here @@ -113,20 +153,22 @@ public partial class Homeowner1 : BehaviourTree //The tree is called from the root every tick protected override BehaviourTreeNode CreateTree() { + Debug.Log("Creating Tree"); //Start from the root, structure it like this to make it look like a tree BehaviourTreeNode root = new BehaviourTreeSelector("Root", new List { new BehaviourTreeSequence("Alerted", new List { - new LeafSearch("SearchFOV", GetComponent(), eyeOffset, sightDistance), + new LeafSearch("SearchFOV"), new BehaviourTreeSequence("CatchPlayer", new List { - new LeafChase("Chasing", GetComponent(), GetComponent(), chaseSpeed, turningSpeed, distanceToCapture, captureTime), - new LeafAttack("Attacking", GameObject.Find("Player").GetValueOrDefault()) + new LeafChase("Chasing"), + new LeafAttack("Attacking") }) }), - new LeafPatrol("Patrol", GetComponent(), patrolSpeed, turningSpeed, GetComponent()) + new LeafPatrol("Patrol") }); + Debug.Log("Tree Created"); return root; } } \ No newline at end of file diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs index 56b5e1ef..b2cfeb52 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs @@ -28,28 +28,41 @@ public partial class LeafAttack : BehaviourTreeNode //FUNCTIONS public partial class LeafAttack : BehaviourTreeNode { - public LeafAttack(string name, GameObject p) : base (name) + public LeafAttack(string name) : base (name) { - player = p; + Debug.Log("LeafAttack ctor"); } public override BehaviourTreeNodeStatus Evaluate() { - //Debug.LogWarning("LeafAttack"); + Debug.LogWarning("LeafAttack"); //Fail if no target in blackboard? onEnter(BehaviourTreeNodeStatus.RUNNING); - //Succeed when stand in hurt box for long enough - //Debug.Log("Attempting to get blackboard data"); - float? captureTime = (float?)GetNodeData("captureTimeLeft"); - //Debug.Log("Got blackboard data"); - if (captureTime == null) + //Get Data + float? captureTime; + if (GetNodeData("captureTimeLeft") == null) { status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); return status; } + else + captureTime = (float)GetNodeData("captureTime"); + + if (GameObject.Find("Player") == null) + { + status = BehaviourTreeNodeStatus.FAILURE; + onExit(BehaviourTreeNodeStatus.FAILURE); + return status; + } + else + player = GameObject.Find("Player").GetValueOrDefault(); + + //Succeed when stand in hurt box for long enough + //Debug.Log("Attempting to get blackboard data"); + //Debug.Log("Got blackboard data"); captureTime -= Time.DeltaTimeF; SetNodeData("captureTimeLeft", captureTime); //Debug.Log(captureTime.ToString()); @@ -64,7 +77,7 @@ public partial class LeafAttack : BehaviourTreeNode //Return running if not success - //Debug.Log("Success: Caught"); + Debug.Log("Success: Caught"); status = BehaviourTreeNodeStatus.RUNNING; onExit(BehaviourTreeNodeStatus.RUNNING); return status; diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs index cab81420..6beeb851 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs @@ -24,9 +24,9 @@ public partial class LeafChase : BehaviourTreeNode private Transform transform; private RigidBody rb; private float chaseSpeed; - private float turnSpeed; + private float turningSpeed; private float captureDistance; - private float captureTime; + private float baseCaptureTime; } //FUNCTIONS @@ -34,29 +34,54 @@ public partial class LeafChase : BehaviourTreeNode { //Despite inheriting from BehaviourTreeNode, we don't have children to this node, //and hence we don't need to inherit its constructors - public LeafChase(string name, Transform t, RigidBody rb, float cSpd, float tSpd, float capDist, float capTime) : base (name) + public LeafChase(string name) : base (name) { - transform = t; + Debug.Log("LeafChase ctor"); + } + + /* + * transform = t; this.rb = rb; chaseSpeed = cSpd; turnSpeed = tSpd; captureDistance = capDist; captureTime = capTime; - } + */ public override BehaviourTreeNodeStatus Evaluate() { - //Debug.LogWarning("LeafChase"); + Debug.LogWarning("LeafChase"); + + onEnter(BehaviourTreeNodeStatus.RUNNING); + + //Get Data + if (GetNodeData("transform") == null || + GetNodeData("rigidBody") == null || + GetNodeData("turningSpeed") == null || + GetNodeData("chaseSpeed") == null || + GetNodeData("distanceToCapture") == null || + GetNodeData("baseCaptureTime") == null) + { + status = BehaviourTreeNodeStatus.FAILURE; + onExit(BehaviourTreeNodeStatus.FAILURE); + return status; + } + else + { + transform = (Transform)GetNodeData("transform"); + rb = (RigidBody)GetNodeData("rigidBody"); + chaseSpeed = (float)GetNodeData("chaseSpeed"); + turningSpeed = (float)GetNodeData("turningSpeed"); + captureDistance = (float)GetNodeData("distanceToCapture"); + baseCaptureTime = (float)GetNodeData("baseCaptureTime"); + } //Fail if no target in blackboard if (GetNodeData("target") == null) { - //Debug.Log("Failure: No target in blackboard"); + Debug.Log("Failure: No target in blackboard"); return BehaviourTreeNodeStatus.FAILURE; } - - onEnter(BehaviourTreeNodeStatus.RUNNING); - Transform target = (Transform)GetNodeData("target"); Vector3 normalisedDifference = target.GlobalPosition - transform.GlobalPosition; @@ -66,7 +91,7 @@ public partial class LeafChase : BehaviourTreeNode //Over maximum distance, stop chase if ((transform.GlobalPosition - target.GlobalPosition).GetMagnitude() > 1000.0f) { - //Debug.Log("Failure: Over maximum distance"); + Debug.Log("Failure: Over maximum distance"); ClearNodeData("target"); if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) @@ -81,7 +106,7 @@ public partial class LeafChase : BehaviourTreeNode } else if (false) //TODO If collided against a wall { - //Debug.Log("Running: Collided against wall"); + Debug.Log("Running: Collided against wall"); SetNodeData("isPathfinding", true); status = BehaviourTreeNodeStatus.RUNNING; @@ -91,15 +116,15 @@ public partial class LeafChase : BehaviourTreeNode //Keep chasing else if ((transform.GlobalPosition - target.GlobalPosition).GetMagnitude() > captureDistance) { - //Debug.Log("Running: Chasing"); + Debug.Log("Running: Chasing"); Quaternion targetRotation = Quaternion.LookRotation(normalisedDifference, new Vector3(0.0f, 1.0f, 0.0f)); - transform.LocalRotation = Quaternion.Slerp(transform.LocalRotation, targetRotation, turnSpeed * Time.DeltaTimeF); + transform.LocalRotation = Quaternion.Slerp(transform.LocalRotation, targetRotation, turningSpeed * Time.DeltaTimeF); //TODO delete this when original intendd code above works with velocity being limited correctly rb.LinearVelocity = normalisedDifference * chaseSpeed; //Reset capture timing to base - SetNodeData("captureTimeLeft", captureTime); + SetNodeData("captureTimeLeft", baseCaptureTime); //Not capturing, don't play SFX SetNodeData("isCapturing", false); @@ -111,10 +136,10 @@ public partial class LeafChase : BehaviourTreeNode //Once player is close enough, perform attack else { - //Debug.Log("Success: Near enough. Begin attack"); + Debug.Log("Success: Near enough. Begin attack"); //Look at the correct direction Quaternion targetRotation = Quaternion.LookRotation(normalisedDifference, new Vector3(0.0f, 1.0f, 0.0f)); - transform.LocalRotation = Quaternion.Slerp(transform.LocalRotation, targetRotation, turnSpeed * Time.DeltaTimeF); + transform.LocalRotation = Quaternion.Slerp(transform.LocalRotation, targetRotation, turningSpeed * Time.DeltaTimeF); //Play SFX if (GetNodeData("isCapturing") != null && (bool)GetNodeData("isCapturing") == false) diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs index 3f66bf94..7a29b7c4 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs @@ -22,7 +22,7 @@ public partial class LeafPatrol : BehaviourTreeNode { //Waypoints and movement private Transform transform; - private List waypoints; + private List? waypoints; private RigidBody rb; private float patrolSpeed; private float turningSpeed; @@ -42,13 +42,8 @@ public partial class LeafPatrol : BehaviourTreeNode //Constructor, establish values here //Despite inheriting from BehaviourTreeNode, we don't have children to this //node, and hence we do not need to inherit its constructors - public LeafPatrol(string name, Transform t, float patrolSpeed, float turnSpeed, RigidBody rb) : base(name) + public LeafPatrol(string name) : base(name) { - transform = t; - this.patrolSpeed = patrolSpeed; - turningSpeed = turnSpeed; - this.rb = rb; - currentWaypointIndex = 0; } @@ -56,9 +51,28 @@ public partial class LeafPatrol : BehaviourTreeNode //le this node keep returning RUNNING as it is the last fallback node on tree public override BehaviourTreeNodeStatus Evaluate() { - //Debug.LogWarning("LeafPatrol"); + Debug.LogWarning("LeafPatrol"); onEnter(BehaviourTreeNodeStatus.RUNNING); - if(GetNodeData("currentWaypointIndex") == null) + + //Get data + if (GetNodeData("transform") == null || + GetNodeData("patrolSpeed") == null || + GetNodeData("turningSpeed") == null || + GetNodeData("rigidBody") == null) + { + status = BehaviourTreeNodeStatus.FAILURE; + onExit(BehaviourTreeNodeStatus.FAILURE); + return status; + } + else + { + transform = (Transform)GetNodeData("transform"); + patrolSpeed = (float)GetNodeData("patrolSpeed"); + turningSpeed = (float)GetNodeData("turningSpeed"); + rb = (RigidBody)GetNodeData("rigidBody"); + } + + if (GetNodeData("currentWaypointIndex") == null) { SetNodeData("currentWaypointIndex", 0); } @@ -73,7 +87,7 @@ public partial class LeafPatrol : BehaviourTreeNode //Move and cycle between waypoints private void MoveToWaypoint() { - //Debug.Log("MoveToWaypoint"); + Debug.Log("MoveToWaypoint"); //Waiting, do not move if (GetNodeData("isWaiting") != null) { @@ -82,19 +96,16 @@ public partial class LeafPatrol : BehaviourTreeNode ClearNodeData("isWaiting"); return; } - waypoints = (List)GetNodeData("waypoints"); if (waypoints == null) { return; } Vector3 targetPosition = waypoints[currentWaypointIndex].GetComponent().GlobalPosition; - //Reach waypoint by X and Z being near enough //Do not consider Y of waypoints yet Vector3 remainingDistance = targetPosition - transform.GlobalPosition; remainingDistance.y = 0.0f; - //Reached waypoint, cycle if (remainingDistance.GetSqrMagnitude() < 0.1f) { @@ -165,7 +176,7 @@ public partial class LeafPatrol : BehaviourTreeNode private void DelayAtWaypoint() { - //Debug.Log("DelayAtWaypoint"); + Debug.Log("DelayAtWaypoint"); waitCounter += Time.DeltaTimeF; if (waitCounter >= waitDuration) isWaiting = false; diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs index 6d8e0237..68a12be7 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs @@ -30,12 +30,9 @@ public partial class LeafSearch : BehaviourTreeNode //FUNCTIONS HERE public partial class LeafSearch : BehaviourTreeNode { - public LeafSearch(string name, Transform t, Vector3 eo, float sDist) : base(name) + public LeafSearch(string name) : base(name) { - transform = t; - eyeOffset = eo; - sightDistance = sDist; - player = null; + Debug.Log("LeafSearch ctor"); } //Helper, find the nearest unobstructed waypoint to return to when chase is over @@ -74,9 +71,26 @@ public partial class LeafSearch : BehaviourTreeNode public override BehaviourTreeNodeStatus Evaluate() { - //Debug.LogWarning("LeafSearch"); + Debug.LogWarning("LeafSearch"); onEnter(BehaviourTreeNodeStatus.RUNNING); + //Get data + if (GetNodeData("transform") == null || + GetNodeData("eyeOffset") == null || + GetNodeData("sightDistance") == null) + { + status = BehaviourTreeNodeStatus.FAILURE; + onExit(BehaviourTreeNodeStatus.FAILURE); + return status; + } + else + { + transform = (Transform)GetNodeData("transform"); + Debug.Log("Transform position: " + transform.GlobalPosition.x + " " + transform.GlobalPosition.y + " " + transform.GlobalPosition.z); + eyeOffset = (Vector3)GetNodeData("eyeOffset"); + sightDistance = (float)GetNodeData("sightDistance"); + } + //Search for player player = GameObject.Find("Player"); @@ -103,7 +117,7 @@ public partial class LeafSearch : BehaviourTreeNode //Fail if too far from vision range if ((plrT.GlobalPosition - transform.GlobalPosition).GetMagnitude() > sightDistance) { - //Debug.Log("Failure: Too far"); + Debug.Log("Failure: Too far"); handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); @@ -118,7 +132,7 @@ public partial class LeafSearch : BehaviourTreeNode //Debug.Log("Dot: " + Vector3.Dot(difference, lookDirection)); if (Vector3.Dot(difference, lookDirection) < 0.0f) { - //Debug.Log("Failure: Out of FOV"); + Debug.Log("Failure: Out of FOV"); handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); @@ -139,7 +153,7 @@ public partial class LeafSearch : BehaviourTreeNode //Diren may likely add ALL objects hit by the ray over December if (sightRayHit.Hit && sightRayHit.Other != player) { - //Debug.Log("Failure: Ray hit obstacle named " + sightRayHit.Other.GetValueOrDefault().Name + " ID" + sightRayHit.Other.GetValueOrDefault().EntityId); + Debug.Log("Failure: Ray hit obstacle named " + sightRayHit.Other.GetValueOrDefault().Name + " ID" + sightRayHit.Other.GetValueOrDefault().EntityId); handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); @@ -147,11 +161,11 @@ public partial class LeafSearch : BehaviourTreeNode } else if (sightRayHit.Hit && sightRayHit.Other == player) { - //Debug.Log("Ray hit player"); + Debug.Log("Ray hit player"); } //All checks for now succeeded - //Debug.Log("Success: Homeowner has sighted player"); + Debug.Log("Success: Homeowner has sighted player"); //Write player's transform into the blackboard SetNodeData("target", plrT);