From d6fab4439f266cb4b4bf42835c16bd6026df602a Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Thu, 24 Nov 2022 21:56:06 +0800 Subject: [PATCH 1/6] Made player jumping more responsive - Changed the input check in the jump function from a GetKeyDown() / GetKeyUp() to a GetKey() / !GetKey() - This makes jumping a lot more responsive - This also means holding the jump button causes the raccoon to "bunny hop" until jump button is released --- Assets/Scripts/Gameplay/Player/SC_PlayerController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs index b8a096e9..ac00e5f7 100644 --- a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs +++ b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs @@ -285,7 +285,7 @@ public class PlayerController : Script { if (currentState == RaccoonStates.WALKING || currentState == RaccoonStates.RUNNING || currentState == RaccoonStates.IDLE) { - if (Input.GetKeyDown(Input.KeyCode.Space) && isGrounded && rb != null) + if (Input.GetKey(Input.KeyCode.Space) && isGrounded && rb != null) { currentState = RaccoonStates.JUMP; Vector3 v = rb.LinearVelocity; @@ -304,7 +304,7 @@ public class PlayerController : Script } } - if(!isGrounded && rb != null && (rb.LinearVelocity.y < 0.0f || Input.GetKeyUp(Input.KeyCode.Space))) + if(!isGrounded && rb != null && (rb.LinearVelocity.y < 0.0f || !Input.GetKey(Input.KeyCode.Space))) currentState = RaccoonStates.FALLING; } -- 2.40.1 From 4daaa8e8979f739155ffc21512be92f02dc7974d Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 25 Nov 2022 00:56:40 +0800 Subject: [PATCH 2/6] Added SFX to AI - Footsteps, alert yell and unalert humming --- .../AIBehaviour/Implemented/Homeowner1.cs | 2 +- .../Implemented/LeafNodes/LeafChase.cs | 2 +- .../Implemented/LeafNodes/LeafSearch.cs | 35 ++++++++----------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs b/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs index a90a3157..8ebd0537 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs @@ -103,7 +103,7 @@ public partial class Homeowner1 : BehaviourTree footstepTimeRemaining -= velocity * Time.DeltaTimeF; if (footstepTimeRemaining < 0.0f) { - Debug.Log("AI Play Footstep SFX"); + Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_footsteps"); footstepTimeRemaining = footstepSFXIntervalMultiplier; } } diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs index 87e8ae1e..10562fc9 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs @@ -71,7 +71,7 @@ public partial class LeafChase : BehaviourTreeNode if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) { - Debug.Log("AI play unalert hmm"); + Audio.PlaySFXOnce2D("event:/Homeowner/humming"); } SetNodeData("isAlert", false); diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs index 056b5a4a..6d8e0237 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs @@ -41,7 +41,6 @@ public partial class LeafSearch : BehaviourTreeNode //Helper, find the nearest unobstructed waypoint to return to when chase is over private void reevaluateWaypoint() { - Debug.Log("Reevaluating Waypoints"); List waypoints = (List)GetNodeData("waypoints"); if (waypoints == null) @@ -62,6 +61,17 @@ public partial class LeafSearch : BehaviourTreeNode SetNodeData("currentWaypointIndex", nearestWaypointIndex); } + //Helper for handling stopping of chases + private void handleChaseStop() + { + if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) + { + Audio.PlaySFXOnce2D("event:/Homeowner/humming"); + reevaluateWaypoint(); + } + SetNodeData("isAlert", false); + } + public override BehaviourTreeNodeStatus Evaluate() { //Debug.LogWarning("LeafSearch"); @@ -94,12 +104,7 @@ public partial class LeafSearch : BehaviourTreeNode if ((plrT.GlobalPosition - transform.GlobalPosition).GetMagnitude() > sightDistance) { //Debug.Log("Failure: Too far"); - if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) - { - Debug.Log("AI play unalert hmm"); - reevaluateWaypoint(); - } - SetNodeData("isAlert", false); + handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); return status; @@ -114,12 +119,7 @@ public partial class LeafSearch : BehaviourTreeNode if (Vector3.Dot(difference, lookDirection) < 0.0f) { //Debug.Log("Failure: Out of FOV"); - if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) - { - Debug.Log("AI play unalert hmm"); - reevaluateWaypoint(); - } - SetNodeData("isAlert", false); + handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); return status; @@ -140,12 +140,7 @@ public partial class LeafSearch : BehaviourTreeNode if (sightRayHit.Hit && sightRayHit.Other != player) { //Debug.Log("Failure: Ray hit obstacle named " + sightRayHit.Other.GetValueOrDefault().Name + " ID" + sightRayHit.Other.GetValueOrDefault().EntityId); - if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) - { - Debug.Log("AI play unalert hmm"); - reevaluateWaypoint(); - } - SetNodeData("isAlert", false); + handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); return status; @@ -162,7 +157,7 @@ public partial class LeafSearch : BehaviourTreeNode if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == false) { - Debug.Log("AI Play Alerted Yell here"); + Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_detect_raccoon"); } SetNodeData("isAlert", true); -- 2.40.1 From c5d490b8b2b2fff747eab90afc8d1a8299507a0a Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 25 Nov 2022 11:44:58 +0800 Subject: [PATCH 3/6] Added null checks for AI blackboard data - Null checks added to prevent AI causing the engine to crash --- .../AIBehaviour/Implemented/LeafNodes/LeafAttack.cs | 10 +++++++++- .../AIBehaviour/Implemented/LeafNodes/LeafChase.cs | 2 +- .../AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs index e64b63ad..56b5e1ef 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs @@ -41,7 +41,15 @@ public partial class LeafAttack : BehaviourTreeNode onEnter(BehaviourTreeNodeStatus.RUNNING); //Succeed when stand in hurt box for long enough - float captureTime = (float)GetNodeData("captureTimeLeft"); + //Debug.Log("Attempting to get blackboard data"); + float? captureTime = (float?)GetNodeData("captureTimeLeft"); + //Debug.Log("Got blackboard data"); + if (captureTime == null) + { + status = BehaviourTreeNodeStatus.FAILURE; + onExit(BehaviourTreeNodeStatus.FAILURE); + return status; + } captureTime -= Time.DeltaTimeF; SetNodeData("captureTimeLeft", captureTime); //Debug.Log(captureTime.ToString()); diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs index 10562fc9..cab81420 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs @@ -119,7 +119,7 @@ public partial class LeafChase : BehaviourTreeNode //Play SFX if (GetNodeData("isCapturing") != null && (bool)GetNodeData("isCapturing") == false) { - Debug.Log("AI Play capturing SFX"); + //Debug.Log("AI Play capturing SFX"); } SetNodeData("isCapturing", true); diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs index 248fa8b9..3f66bf94 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs @@ -84,6 +84,10 @@ public partial class LeafPatrol : BehaviourTreeNode } waypoints = (List)GetNodeData("waypoints"); + if (waypoints == null) + { + return; + } Vector3 targetPosition = waypoints[currentWaypointIndex].GetComponent().GlobalPosition; //Reach waypoint by X and Z being near enough -- 2.40.1 From 7003262a5d6ddde17a87b6a711ce9266b273338a Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 25 Nov 2022 16:12:58 +0800 Subject: [PATCH 4/6] 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); -- 2.40.1 From 5b41e832c64772f4519116c4a6d670be48edbc82 Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 25 Nov 2022 20:16:31 +0800 Subject: [PATCH 5/6] Enhanced AI with better chase logic - AI now keeps track of last waypoint he has seen player at and heads there in an attempt to chase him down - AI can be made to reverse his chase/patrol path by running around him - The scene with the AI fix is called "MainGameWithAIFixed" --- Assets/Scenes/MainGameWithAIFixed.shade | 5 +- .../BehaviourTree/Core/BehaviourTree.cs | 1 + .../AIBehaviour/Implemented/Homeowner1.cs | 15 ++- .../Implemented/LeafNodes/LeafAttack.cs | 36 +++++-- .../Implemented/LeafNodes/LeafChase.cs | 66 +++++++++--- .../Implemented/LeafNodes/LeafPatrol.cs | 102 ++++++++++++++++-- .../Implemented/LeafNodes/LeafSearch.cs | 51 ++++++--- 7 files changed, 219 insertions(+), 57 deletions(-) diff --git a/Assets/Scenes/MainGameWithAIFixed.shade b/Assets/Scenes/MainGameWithAIFixed.shade index 4a987708..d30799bc 100644 --- a/Assets/Scenes/MainGameWithAIFixed.shade +++ b/Assets/Scenes/MainGameWithAIFixed.shade @@ -8599,6 +8599,7 @@ Arm Length: 1 Look At Camera Origin: true Target Offset: {x: 0, y: 0, z: 0} + Camera Collision: false IsActive: true Scripts: - Type: SHADE_Scripting.ThirdPersonCamera @@ -8640,7 +8641,7 @@ Components: Transform Component: Translate: {x: 2.70000005, y: 0.100000001, z: -2} - Rotate: {x: -0, y: 0, z: -0} + Rotate: {x: -0, y: -2.09439516, z: -0} Scale: {x: 1, y: 1, z: 1} IsActive: true Renderable Component: @@ -8665,7 +8666,7 @@ Colliders: - Is Trigger: false Type: Box - Half Extents: {x: 0.200000003, y: 0.899999976, z: 0.200000003} + Half Extents: {x: 0.400000006, y: 1.79999995, z: 0.400000006} 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 cdced78e..092c4087 100644 --- a/Assets/Scripts/AIBehaviour/BehaviourTree/Core/BehaviourTree.cs +++ b/Assets/Scripts/AIBehaviour/BehaviourTree/Core/BehaviourTree.cs @@ -74,6 +74,7 @@ namespace SHADE_Scripting.AIBehaviour.BehaviourTree } else { + //Debug.LogError("Cannot retrieve data " + key); return outData; } } diff --git a/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs b/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs index 67c1034c..ff315df2 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/Homeowner1.cs @@ -104,15 +104,14 @@ public partial class Homeowner1 : BehaviourTree //Called every tick protected override void Tick() { - Debug.Log("Ticking"); + //Debug.Log("Ticking"); //Update data if (GetData("waypoints") == null) { - if (waypointsPool) + if (waypointsPool != GameObject.Null) SetData("waypoints", (List)waypointsPool.GetChildren()); - - List wpTemp = (List)GetData("waypoints"); - Debug.Log(wpTemp.Count.ToString()); + else + Debug.LogError("No waypoints, no AI"); } if (GetData("transform") == null) SetData("transform", GetComponent()); @@ -145,7 +144,7 @@ public partial class Homeowner1 : BehaviourTree Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_footsteps"); footstepTimeRemaining = footstepSFXIntervalMultiplier; } - Debug.Log("Ticked"); + //Debug.Log("Ticked"); } //Define the behaviour tree here @@ -153,7 +152,7 @@ public partial class Homeowner1 : BehaviourTree //The tree is called from the root every tick protected override BehaviourTreeNode CreateTree() { - Debug.Log("Creating Tree"); + //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 { @@ -168,7 +167,7 @@ public partial class Homeowner1 : BehaviourTree }), new LeafPatrol("Patrol") }); - Debug.Log("Tree Created"); + //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 b2cfeb52..71a23115 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafAttack.cs @@ -21,7 +21,7 @@ using System.Threading.Tasks; //VARIABLES public partial class LeafAttack : BehaviourTreeNode { - //Holds the player game object + //Holds the player game object that is to be targeted private GameObject player; } @@ -30,12 +30,36 @@ public partial class LeafAttack : BehaviourTreeNode { public LeafAttack(string name) : base (name) { - Debug.Log("LeafAttack ctor"); + //Debug.Log("LeafAttack ctor"); + } + + //Helper, find the nearest unobstructed waypoint to return to when chase is over + public void reevaluateWaypoint() + { + List waypoints = (List)GetNodeData("waypoints"); + Transform transform = (Transform)GetNodeData("transform"); + + if (waypoints == null || transform == null) + { + SetNodeData("currentWaypointIndex", 0); + return; + } + + int nearestWaypointIndex = 0; + for (int i = 0; i < waypoints.Count; ++i) + { + if ((transform.GlobalPosition - waypoints[i].GetComponent().GlobalPosition).GetSqrMagnitude() < + (transform.GlobalPosition - waypoints[nearestWaypointIndex].GetComponent().GlobalPosition).GetSqrMagnitude()) + { + nearestWaypointIndex = i; + } + } + SetNodeData("currentWaypointIndex", nearestWaypointIndex); } public override BehaviourTreeNodeStatus Evaluate() { - Debug.LogWarning("LeafAttack"); + //Debug.LogWarning("LeafAttack"); //Fail if no target in blackboard? onEnter(BehaviourTreeNodeStatus.RUNNING); @@ -49,7 +73,7 @@ public partial class LeafAttack : BehaviourTreeNode return status; } else - captureTime = (float)GetNodeData("captureTime"); + captureTime = (float)GetNodeData("captureTimeLeft"); if (GameObject.Find("Player") == null) { @@ -69,6 +93,7 @@ public partial class LeafAttack : BehaviourTreeNode if (captureTime <= 0.0f) { //Catch player when in range for long enough + //Debug.Log("Success: Caught"); player.GetScript().currentState = PlayerController.RaccoonStates.CAUGHT; status = BehaviourTreeNodeStatus.SUCCESS; onExit(BehaviourTreeNodeStatus.SUCCESS); @@ -76,8 +101,7 @@ public partial class LeafAttack : BehaviourTreeNode } //Return running if not success - - Debug.Log("Success: Caught"); + //Debug.Log("Running: About to capture in " + captureTimeLeft); 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 6beeb851..de3352d6 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafChase.cs @@ -36,21 +36,36 @@ public partial class LeafChase : BehaviourTreeNode //and hence we don't need to inherit its constructors public LeafChase(string name) : base (name) { - Debug.Log("LeafChase ctor"); + //Debug.Log("LeafChase ctor"); } - /* - * transform = t; - this.rb = rb; - chaseSpeed = cSpd; - turnSpeed = tSpd; - captureDistance = capDist; - captureTime = capTime; - */ + //Helper, find which waypoint player is closest to + private void determinePlayerWaypoint() + { + List waypoints = (List)GetNodeData("waypoints"); + Transform target = (Transform)GetNodeData("target"); + if (waypoints == null || target == null) + { + return; + } + + int nearestWaypointIndex = 0; + for (int i = 0; i < waypoints.Count; ++i) + { + if ((target.GlobalPosition - waypoints[i].GetComponent().GlobalPosition).GetSqrMagnitude() < + (target.GlobalPosition - waypoints[nearestWaypointIndex].GetComponent().GlobalPosition).GetSqrMagnitude()) + { + nearestWaypointIndex = i; + } + } + //Debug.Log("Player is nearest " + nearestWaypointIndex); + //Debug.Log("I'm at " + (int)GetNodeData("currentWaypointIndex")); + SetNodeData("playerLastSightedWaypointIndex", nearestWaypointIndex); + } public override BehaviourTreeNodeStatus Evaluate() { - Debug.LogWarning("LeafChase"); + //Debug.LogWarning("LeafChase"); onEnter(BehaviourTreeNodeStatus.RUNNING); @@ -79,7 +94,7 @@ public partial class LeafChase : BehaviourTreeNode //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; } Transform target = (Transform)GetNodeData("target"); @@ -91,7 +106,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) @@ -106,7 +121,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; @@ -116,12 +131,31 @@ 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, turningSpeed * Time.DeltaTimeF); + + //Determine the player's nearest waypoint as long as the AI can see the player + //Head towards that waypoint in an attempt to chase the player + determinePlayerWaypoint(); + //TODO delete this when original intendd code above works with velocity being limited correctly - rb.LinearVelocity = normalisedDifference * chaseSpeed; + //Only chase the player directly if the player's waypoint matches the AI's own + if (GetNodeData("currentWaypointIndex") != null && GetNodeData("playerLastSightedWaypointIndex") != null) + { + if ((int)GetNodeData("currentWaypointIndex") == (int)GetNodeData("playerLastSightedWaypointIndex")) + { + //Debug.Log("Waypoint indicees matching. Chasing directly"); + rb.LinearVelocity = normalisedDifference * chaseSpeed; + } + else + { + status = BehaviourTreeNodeStatus.FAILURE; + onExit(BehaviourTreeNodeStatus.FAILURE); + return BehaviourTreeNodeStatus.FAILURE; + } + } //Reset capture timing to base SetNodeData("captureTimeLeft", baseCaptureTime); @@ -136,7 +170,7 @@ 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, turningSpeed * Time.DeltaTimeF); diff --git a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs index 7a29b7c4..2f9c8e1a 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafPatrol.cs @@ -25,10 +25,12 @@ public partial class LeafPatrol : BehaviourTreeNode private List? waypoints; private RigidBody rb; private float patrolSpeed; + private float chaseSpeed; private float turningSpeed; private float retreatTimer = 0.0f; private int currentWaypointIndex = 0; private bool retreatState = false; + private bool goingForwards = true; //Small delays between waypoints private bool isWaiting = false; @@ -51,12 +53,13 @@ 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); //Get data if (GetNodeData("transform") == null || GetNodeData("patrolSpeed") == null || + GetNodeData("chaseSpeed") == null || GetNodeData("turningSpeed") == null || GetNodeData("rigidBody") == null) { @@ -68,6 +71,7 @@ public partial class LeafPatrol : BehaviourTreeNode { transform = (Transform)GetNodeData("transform"); patrolSpeed = (float)GetNodeData("patrolSpeed"); + chaseSpeed = (float)GetNodeData("chaseSpeed"); turningSpeed = (float)GetNodeData("turningSpeed"); rb = (RigidBody)GetNodeData("rigidBody"); } @@ -87,11 +91,14 @@ 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) { - waitCounter = 0.0f; + //Only wait to change waypoints if not alert + if (GetNodeData("isAlert") != null && !(bool)GetNodeData("isAlert")) + waitCounter = 0.0f; + isWaiting = true; ClearNodeData("isWaiting"); return; @@ -109,15 +116,69 @@ public partial class LeafPatrol : BehaviourTreeNode //Reached waypoint, cycle if (remainingDistance.GetSqrMagnitude() < 0.1f) { + //If alert, may reverse + if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert")) + { + //If alert, may reverse if it's closer to the player + if (GetNodeData("playerLastSightedWaypointIndex") != null) + { + int playerWaypoint = (int)GetNodeData("playerLastSightedWaypointIndex"); + int forwardDistance = 0; + int backDistance = 0; + if (playerWaypoint < currentWaypointIndex) + { + //Player waypoint is behind current waypoint + forwardDistance = playerWaypoint + waypoints.Count() - currentWaypointIndex; + backDistance = currentWaypointIndex - playerWaypoint; + } + else + { + //Player waypoint is ahead of current waypoint (or same) + forwardDistance = playerWaypoint - currentWaypointIndex; + backDistance = currentWaypointIndex + waypoints.Count() - playerWaypoint; + } + + if (backDistance < forwardDistance) + { + //Go backwards + goingForwards = false; + + } + else + { + //Go forward + goingForwards = true; + } + } + else + { + //Fallback if no player waypoint data, go forward + goingForwards = true; + } + } + //Cycle waypoints - ++currentWaypointIndex; - if (currentWaypointIndex >= waypoints.Count()) - currentWaypointIndex = 0; + if (goingForwards) + { + ++currentWaypointIndex; + if (currentWaypointIndex >= waypoints.Count()) + currentWaypointIndex = 0; + } + else + { + --currentWaypointIndex; + if (currentWaypointIndex < 0) + currentWaypointIndex = waypoints.Count() - 1; + } + //Write to blackboard SetNodeData("currentWaypointIndex", currentWaypointIndex); - waitCounter = 0.0f; + //Only wait to change waypoints if not alert + if (GetNodeData("isAlert") != null && !(bool)GetNodeData("isAlert")) + waitCounter = 0.0f; + isWaiting = true; } else if (false /*Physics.OverlapSphere(_selfTransform.position, 0.3f, 1 << 8).Length > 0 && retreatState == false*/) @@ -159,8 +220,30 @@ public partial class LeafPatrol : BehaviourTreeNode //TODO delete this when original intended code above works with velocity being limited correctly if (rb != null) { - //Debug.Log("Null check passed?"); - rb.LinearVelocity = normalisedDifference * patrolSpeed; + //Move quickly if alert + if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert")) + { + //Debug.Log("Fast Patrol"); + rb.LinearVelocity = normalisedDifference * chaseSpeed; + } + else + { + rb.LinearVelocity = normalisedDifference * patrolSpeed; + } + + //Unalert if AI reaches player nearest + if (GetNodeData("currentWaypointIndex") != null && GetNodeData("playerLastSightedWaypointIndex") != null) + { + if ((int)GetNodeData("currentWaypointIndex") == (int)GetNodeData("playerLastSightedWaypointIndex")) + { + if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert")) + { + //Debug.Log("Unalert"); + Audio.PlaySFXOnce2D("event:/Homeowner/humming"); + } + SetNodeData("isAlert", false); + } + } } if (retreatState) { @@ -176,7 +259,6 @@ public partial class LeafPatrol : BehaviourTreeNode private void 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 68a12be7..4fa5e376 100644 --- a/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs +++ b/Assets/Scripts/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs @@ -32,11 +32,11 @@ public partial class LeafSearch : BehaviourTreeNode { public LeafSearch(string name) : base(name) { - Debug.Log("LeafSearch ctor"); + //Debug.Log("LeafSearch ctor"); } //Helper, find the nearest unobstructed waypoint to return to when chase is over - private void reevaluateWaypoint() + public void reevaluateWaypoint() { List waypoints = (List)GetNodeData("waypoints"); @@ -58,6 +58,8 @@ public partial class LeafSearch : BehaviourTreeNode SetNodeData("currentWaypointIndex", nearestWaypointIndex); } + //Helper for handling being alert + //Helper for handling stopping of chases private void handleChaseStop() { @@ -71,7 +73,7 @@ public partial class LeafSearch : BehaviourTreeNode public override BehaviourTreeNodeStatus Evaluate() { - Debug.LogWarning("LeafSearch"); + //Debug.LogWarning("LeafSearch"); onEnter(BehaviourTreeNodeStatus.RUNNING); //Get data @@ -86,7 +88,6 @@ public partial class LeafSearch : BehaviourTreeNode 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"); } @@ -117,8 +118,8 @@ public partial class LeafSearch : BehaviourTreeNode //Fail if too far from vision range if ((plrT.GlobalPosition - transform.GlobalPosition).GetMagnitude() > sightDistance) { - Debug.Log("Failure: Too far"); - handleChaseStop(); + //Debug.Log("Failure: Too far"); + //handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); return status; @@ -132,8 +133,8 @@ 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"); - handleChaseStop(); + //Debug.Log("Failure: Out of FOV"); + //handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); return status; @@ -146,34 +147,54 @@ public partial class LeafSearch : BehaviourTreeNode //Draw a ray, succeed if ray is unobstructed Vector3 eyePosition = transform.GlobalPosition + eyeOffset; - Ray sightRay = new Ray(eyePosition, plrT.GlobalPosition - eyePosition); + BoxCollider playerCollider = player.GetValueOrDefault().GetComponent().GetCollisionShape(0); + if (playerCollider == null) + { + //Debug.Log("Failure: Player has no collider"); + status = BehaviourTreeNodeStatus.FAILURE; + onExit(BehaviourTreeNodeStatus.FAILURE); + return status; + } + //Ray destination to target the centre of the player's collider instead of transform position + //Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable + Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset; + Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition); RaycastHit sightRayHit = Physics.Raycast(sightRay); //As of November 2022, RaycastHit contains only the FIRST object hit by //the ray in the Other GameObject data member //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); - handleChaseStop(); + //TODO sometimes the ray doesn't hit the player even if he's in plain sight because the ray hits the floor the player is on instead??? + //Debug.Log("Failure: Ray hit obstacle named " + sightRayHit.Other.GetValueOrDefault().Name + " ID" + sightRayHit.Other.GetValueOrDefault().EntityId); + //handleChaseStop(); status = BehaviourTreeNodeStatus.FAILURE; onExit(BehaviourTreeNodeStatus.FAILURE); return status; } 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); - if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == false) + if (GetNodeData("isAlert") == null) { + SetNodeData("isAlert", true); Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_detect_raccoon"); } - SetNodeData("isAlert", true); + else + { + if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == false) + { + Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_detect_raccoon"); + } + SetNodeData("isAlert", true); + } status = BehaviourTreeNodeStatus.SUCCESS; onExit(BehaviourTreeNodeStatus.SUCCESS); -- 2.40.1 From 609be908f967deff0df58c0ffe861ecfee2b4acf Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 25 Nov 2022 20:18:36 +0800 Subject: [PATCH 6/6] Revert "Made player jumping more responsive" This reverts commit d6fab4439f266cb4b4bf42835c16bd6026df602a. --- Assets/Scripts/Gameplay/Player/SC_PlayerController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs index 5e5f7f08..47dd2c41 100644 --- a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs +++ b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs @@ -285,7 +285,7 @@ public class PlayerController : Script { if (currentState == RaccoonStates.WALKING || currentState == RaccoonStates.RUNNING || currentState == RaccoonStates.IDLE) { - if (Input.GetKey(Input.KeyCode.Space) && isGrounded && rb != null) + if (Input.GetKeyDown(Input.KeyCode.Space) && isGrounded && rb != null) { currentState = RaccoonStates.JUMP; Vector3 v = rb.LinearVelocity; @@ -304,7 +304,7 @@ public class PlayerController : Script } } - if(!isGrounded && rb != null && (rb.LinearVelocity.y < 0.0f || !Input.GetKey(Input.KeyCode.Space))) + if(!isGrounded && rb != null && (rb.LinearVelocity.y < 0.0f || Input.GetKeyUp(Input.KeyCode.Space))) currentState = RaccoonStates.FALLING; } -- 2.40.1