Fixed AI C# Script for final submission #283

Merged
mushgunAX merged 8 commits from AIFinalFixesGAM300M3 into main 2022-11-25 22:33:58 +08:00
7 changed files with 172 additions and 60 deletions
Showing only changes of commit 7003262a5d - Show all commits

View File

@ -8665,7 +8665,7 @@
Colliders: Colliders:
- Is Trigger: false - Is Trigger: false
Type: Box 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 Friction: 0.400000006
Bounciness: 0 Bounciness: 0
Density: 1 Density: 1

View File

@ -66,9 +66,16 @@ namespace SHADE_Scripting.AIBehaviour.BehaviourTree
//Getters and setters for the blackboard //Getters and setters for the blackboard
public object GetData(string key) public object GetData(string key)
{ {
//Debug.Log("Getting Data " + key);
object outData = null; object outData = null;
if (blackboard.TryGetValue(key, out outData)) return outData; if (blackboard.TryGetValue(key, out outData))
else return outData; {
return outData;
}
else
{
return outData;
}
} }
public void SetData(string key, object data) public void SetData(string key, object data)
{ {

View File

@ -84,17 +84,56 @@ public partial class Homeowner1 : BehaviourTree
_events = new Homeowner1Events(this); _events = new Homeowner1Events(this);
events.Initialise(); events.Initialise();
//Initialise the waypoints here //(25 Nov) DO NOT Initialise the data here
if (waypointsPool) /*if (waypointsPool)
{ {
waypoints = (List<GameObject>)waypointsPool.GetChildren(); waypoints = (List<GameObject>)waypointsPool.GetChildren();
SetData("waypoints", waypoints); SetData("waypoints", waypoints);
} }
SetData("transform", GetComponent<Transform>());
SetData("rigidBody", GetComponent<RigidBody>());
SetData("eyeOffset", eyeOffset);
SetData("sightDistance", sightDistance);
SetData("patrolSpeed", patrolSpeed);
SetData("chaseSpeed", chaseSpeed);
SetData("turningSpeed", turningSpeed);
SetData("distanceToCapture", distanceToCapture);
SetData("baseCaptureTime", captureTime);*/
} }
//Called every tick //Called every tick
protected override void Tick() protected override void Tick()
{ {
Debug.Log("Ticking");
//Update data
if (GetData("waypoints") == null)
{
if (waypointsPool)
SetData("waypoints", (List<GameObject>)waypointsPool.GetChildren());
List<GameObject> wpTemp = (List<GameObject>)GetData("waypoints");
Debug.Log(wpTemp.Count.ToString());
}
if (GetData("transform") == null)
SetData("transform", GetComponent<Transform>());
if (GetData("rigidBody") == null)
SetData("rigidBody", GetComponent<RigidBody>());
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(); events.Tick();
//Footsteps SFX, move them somewhere else soon //Footsteps SFX, move them somewhere else soon
@ -106,6 +145,7 @@ public partial class Homeowner1 : BehaviourTree
Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_footsteps"); Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_footsteps");
footstepTimeRemaining = footstepSFXIntervalMultiplier; footstepTimeRemaining = footstepSFXIntervalMultiplier;
} }
Debug.Log("Ticked");
} }
//Define the behaviour tree here //Define the behaviour tree here
@ -113,20 +153,22 @@ public partial class Homeowner1 : BehaviourTree
//The tree is called from the root every tick //The tree is called from the root every tick
protected override BehaviourTreeNode CreateTree() protected override BehaviourTreeNode CreateTree()
{ {
Debug.Log("Creating Tree");
//Start from the root, structure it like this to make it look like a tree //Start from the root, structure it like this to make it look like a tree
BehaviourTreeNode root = new BehaviourTreeSelector("Root", new List<BehaviourTreeNode> BehaviourTreeNode root = new BehaviourTreeSelector("Root", new List<BehaviourTreeNode>
{ {
new BehaviourTreeSequence("Alerted", new List<BehaviourTreeNode> new BehaviourTreeSequence("Alerted", new List<BehaviourTreeNode>
{ {
new LeafSearch("SearchFOV", GetComponent<Transform>(), eyeOffset, sightDistance), new LeafSearch("SearchFOV"),
new BehaviourTreeSequence("CatchPlayer", new List<BehaviourTreeNode> new BehaviourTreeSequence("CatchPlayer", new List<BehaviourTreeNode>
{ {
new LeafChase("Chasing", GetComponent<Transform>(), GetComponent<RigidBody>(), chaseSpeed, turningSpeed, distanceToCapture, captureTime), new LeafChase("Chasing"),
new LeafAttack("Attacking", GameObject.Find("Player").GetValueOrDefault()) new LeafAttack("Attacking")
}) })
}), }),
new LeafPatrol("Patrol", GetComponent<Transform>(), patrolSpeed, turningSpeed, GetComponent<RigidBody>()) new LeafPatrol("Patrol")
}); });
Debug.Log("Tree Created");
return root; return root;
} }
} }

View File

@ -28,28 +28,41 @@ public partial class LeafAttack : BehaviourTreeNode
//FUNCTIONS //FUNCTIONS
public partial class LeafAttack : BehaviourTreeNode 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() public override BehaviourTreeNodeStatus Evaluate()
{ {
//Debug.LogWarning("LeafAttack"); Debug.LogWarning("LeafAttack");
//Fail if no target in blackboard? //Fail if no target in blackboard?
onEnter(BehaviourTreeNodeStatus.RUNNING); onEnter(BehaviourTreeNodeStatus.RUNNING);
//Succeed when stand in hurt box for long enough //Get Data
//Debug.Log("Attempting to get blackboard data"); float? captureTime;
float? captureTime = (float?)GetNodeData("captureTimeLeft"); if (GetNodeData("captureTimeLeft") == null)
//Debug.Log("Got blackboard data");
if (captureTime == null)
{ {
status = BehaviourTreeNodeStatus.FAILURE; status = BehaviourTreeNodeStatus.FAILURE;
onExit(BehaviourTreeNodeStatus.FAILURE); onExit(BehaviourTreeNodeStatus.FAILURE);
return status; 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; captureTime -= Time.DeltaTimeF;
SetNodeData("captureTimeLeft", captureTime); SetNodeData("captureTimeLeft", captureTime);
//Debug.Log(captureTime.ToString()); //Debug.Log(captureTime.ToString());
@ -64,7 +77,7 @@ public partial class LeafAttack : BehaviourTreeNode
//Return running if not success //Return running if not success
//Debug.Log("Success: Caught"); Debug.Log("Success: Caught");
status = BehaviourTreeNodeStatus.RUNNING; status = BehaviourTreeNodeStatus.RUNNING;
onExit(BehaviourTreeNodeStatus.RUNNING); onExit(BehaviourTreeNodeStatus.RUNNING);
return status; return status;

View File

@ -24,9 +24,9 @@ public partial class LeafChase : BehaviourTreeNode
private Transform transform; private Transform transform;
private RigidBody rb; private RigidBody rb;
private float chaseSpeed; private float chaseSpeed;
private float turnSpeed; private float turningSpeed;
private float captureDistance; private float captureDistance;
private float captureTime; private float baseCaptureTime;
} }
//FUNCTIONS //FUNCTIONS
@ -34,29 +34,54 @@ public partial class LeafChase : BehaviourTreeNode
{ {
//Despite inheriting from BehaviourTreeNode, we don't have children to this node, //Despite inheriting from BehaviourTreeNode, we don't have children to this node,
//and hence we don't need to inherit its constructors //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; this.rb = rb;
chaseSpeed = cSpd; chaseSpeed = cSpd;
turnSpeed = tSpd; turnSpeed = tSpd;
captureDistance = capDist; captureDistance = capDist;
captureTime = capTime; captureTime = capTime;
} */
public override BehaviourTreeNodeStatus Evaluate() 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 //Fail if no target in blackboard
if (GetNodeData("target") == null) if (GetNodeData("target") == null)
{ {
//Debug.Log("Failure: No target in blackboard"); Debug.Log("Failure: No target in blackboard");
return BehaviourTreeNodeStatus.FAILURE; return BehaviourTreeNodeStatus.FAILURE;
} }
onEnter(BehaviourTreeNodeStatus.RUNNING);
Transform target = (Transform)GetNodeData("target"); Transform target = (Transform)GetNodeData("target");
Vector3 normalisedDifference = target.GlobalPosition - transform.GlobalPosition; Vector3 normalisedDifference = target.GlobalPosition - transform.GlobalPosition;
@ -66,7 +91,7 @@ public partial class LeafChase : BehaviourTreeNode
//Over maximum distance, stop chase //Over maximum distance, stop chase
if ((transform.GlobalPosition - target.GlobalPosition).GetMagnitude() > 1000.0f) if ((transform.GlobalPosition - target.GlobalPosition).GetMagnitude() > 1000.0f)
{ {
//Debug.Log("Failure: Over maximum distance"); Debug.Log("Failure: Over maximum distance");
ClearNodeData("target"); ClearNodeData("target");
if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) 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 else if (false) //TODO If collided against a wall
{ {
//Debug.Log("Running: Collided against wall"); Debug.Log("Running: Collided against wall");
SetNodeData("isPathfinding", true); SetNodeData("isPathfinding", true);
status = BehaviourTreeNodeStatus.RUNNING; status = BehaviourTreeNodeStatus.RUNNING;
@ -91,15 +116,15 @@ public partial class LeafChase : BehaviourTreeNode
//Keep chasing //Keep chasing
else if ((transform.GlobalPosition - target.GlobalPosition).GetMagnitude() > captureDistance) 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)); 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 //TODO delete this when original intendd code above works with velocity being limited correctly
rb.LinearVelocity = normalisedDifference * chaseSpeed; rb.LinearVelocity = normalisedDifference * chaseSpeed;
//Reset capture timing to base //Reset capture timing to base
SetNodeData("captureTimeLeft", captureTime); SetNodeData("captureTimeLeft", baseCaptureTime);
//Not capturing, don't play SFX //Not capturing, don't play SFX
SetNodeData("isCapturing", false); SetNodeData("isCapturing", false);
@ -111,10 +136,10 @@ public partial class LeafChase : BehaviourTreeNode
//Once player is close enough, perform attack //Once player is close enough, perform attack
else else
{ {
//Debug.Log("Success: Near enough. Begin attack"); Debug.Log("Success: Near enough. Begin attack");
//Look at the correct direction //Look at the correct direction
Quaternion targetRotation = Quaternion.LookRotation(normalisedDifference, new Vector3(0.0f, 1.0f, 0.0f)); 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 //Play SFX
if (GetNodeData("isCapturing") != null && (bool)GetNodeData("isCapturing") == false) if (GetNodeData("isCapturing") != null && (bool)GetNodeData("isCapturing") == false)

View File

@ -22,7 +22,7 @@ public partial class LeafPatrol : BehaviourTreeNode
{ {
//Waypoints and movement //Waypoints and movement
private Transform transform; private Transform transform;
private List<GameObject> waypoints; private List<GameObject>? waypoints;
private RigidBody rb; private RigidBody rb;
private float patrolSpeed; private float patrolSpeed;
private float turningSpeed; private float turningSpeed;
@ -42,13 +42,8 @@ public partial class LeafPatrol : BehaviourTreeNode
//Constructor, establish values here //Constructor, establish values here
//Despite inheriting from BehaviourTreeNode, we don't have children to this //Despite inheriting from BehaviourTreeNode, we don't have children to this
//node, and hence we do not need to inherit its constructors //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; currentWaypointIndex = 0;
} }
@ -56,8 +51,27 @@ public partial class LeafPatrol : BehaviourTreeNode
//le this node keep returning RUNNING as it is the last fallback node on tree //le this node keep returning RUNNING as it is the last fallback node on tree
public override BehaviourTreeNodeStatus Evaluate() public override BehaviourTreeNodeStatus Evaluate()
{ {
//Debug.LogWarning("LeafPatrol"); Debug.LogWarning("LeafPatrol");
onEnter(BehaviourTreeNodeStatus.RUNNING); onEnter(BehaviourTreeNodeStatus.RUNNING);
//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) if (GetNodeData("currentWaypointIndex") == null)
{ {
SetNodeData("currentWaypointIndex", 0); SetNodeData("currentWaypointIndex", 0);
@ -73,7 +87,7 @@ public partial class LeafPatrol : BehaviourTreeNode
//Move and cycle between waypoints //Move and cycle between waypoints
private void MoveToWaypoint() private void MoveToWaypoint()
{ {
//Debug.Log("MoveToWaypoint"); Debug.Log("MoveToWaypoint");
//Waiting, do not move //Waiting, do not move
if (GetNodeData("isWaiting") != null) if (GetNodeData("isWaiting") != null)
{ {
@ -82,19 +96,16 @@ public partial class LeafPatrol : BehaviourTreeNode
ClearNodeData("isWaiting"); ClearNodeData("isWaiting");
return; return;
} }
waypoints = (List<GameObject>)GetNodeData("waypoints"); waypoints = (List<GameObject>)GetNodeData("waypoints");
if (waypoints == null) if (waypoints == null)
{ {
return; return;
} }
Vector3 targetPosition = waypoints[currentWaypointIndex].GetComponent<Transform>().GlobalPosition; Vector3 targetPosition = waypoints[currentWaypointIndex].GetComponent<Transform>().GlobalPosition;
//Reach waypoint by X and Z being near enough //Reach waypoint by X and Z being near enough
//Do not consider Y of waypoints yet //Do not consider Y of waypoints yet
Vector3 remainingDistance = targetPosition - transform.GlobalPosition; Vector3 remainingDistance = targetPosition - transform.GlobalPosition;
remainingDistance.y = 0.0f; remainingDistance.y = 0.0f;
//Reached waypoint, cycle //Reached waypoint, cycle
if (remainingDistance.GetSqrMagnitude() < 0.1f) if (remainingDistance.GetSqrMagnitude() < 0.1f)
{ {
@ -165,7 +176,7 @@ public partial class LeafPatrol : BehaviourTreeNode
private void DelayAtWaypoint() private void DelayAtWaypoint()
{ {
//Debug.Log("DelayAtWaypoint"); Debug.Log("DelayAtWaypoint");
waitCounter += Time.DeltaTimeF; waitCounter += Time.DeltaTimeF;
if (waitCounter >= waitDuration) if (waitCounter >= waitDuration)
isWaiting = false; isWaiting = false;

View File

@ -30,12 +30,9 @@ public partial class LeafSearch : BehaviourTreeNode
//FUNCTIONS HERE //FUNCTIONS HERE
public partial class LeafSearch : BehaviourTreeNode 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; Debug.Log("LeafSearch ctor");
eyeOffset = eo;
sightDistance = sDist;
player = null;
} }
//Helper, find the nearest unobstructed waypoint to return to when chase is over //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() public override BehaviourTreeNodeStatus Evaluate()
{ {
//Debug.LogWarning("LeafSearch"); Debug.LogWarning("LeafSearch");
onEnter(BehaviourTreeNodeStatus.RUNNING); 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 //Search for player
player = GameObject.Find("Player"); player = GameObject.Find("Player");
@ -103,7 +117,7 @@ public partial class LeafSearch : BehaviourTreeNode
//Fail if too far from vision range //Fail if too far from vision range
if ((plrT.GlobalPosition - transform.GlobalPosition).GetMagnitude() > sightDistance) if ((plrT.GlobalPosition - transform.GlobalPosition).GetMagnitude() > sightDistance)
{ {
//Debug.Log("Failure: Too far"); Debug.Log("Failure: Too far");
handleChaseStop(); handleChaseStop();
status = BehaviourTreeNodeStatus.FAILURE; status = BehaviourTreeNodeStatus.FAILURE;
onExit(BehaviourTreeNodeStatus.FAILURE); onExit(BehaviourTreeNodeStatus.FAILURE);
@ -118,7 +132,7 @@ public partial class LeafSearch : BehaviourTreeNode
//Debug.Log("Dot: " + Vector3.Dot(difference, lookDirection)); //Debug.Log("Dot: " + Vector3.Dot(difference, lookDirection));
if (Vector3.Dot(difference, lookDirection) < 0.0f) if (Vector3.Dot(difference, lookDirection) < 0.0f)
{ {
//Debug.Log("Failure: Out of FOV"); Debug.Log("Failure: Out of FOV");
handleChaseStop(); handleChaseStop();
status = BehaviourTreeNodeStatus.FAILURE; status = BehaviourTreeNodeStatus.FAILURE;
onExit(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 //Diren may likely add ALL objects hit by the ray over December
if (sightRayHit.Hit && sightRayHit.Other != player) 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(); handleChaseStop();
status = BehaviourTreeNodeStatus.FAILURE; status = BehaviourTreeNodeStatus.FAILURE;
onExit(BehaviourTreeNodeStatus.FAILURE); onExit(BehaviourTreeNodeStatus.FAILURE);
@ -147,11 +161,11 @@ public partial class LeafSearch : BehaviourTreeNode
} }
else if (sightRayHit.Hit && sightRayHit.Other == player) else if (sightRayHit.Hit && sightRayHit.Other == player)
{ {
//Debug.Log("Ray hit player"); Debug.Log("Ray hit player");
} }
//All checks for now succeeded //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 //Write player's transform into the blackboard
SetNodeData("target", plrT); SetNodeData("target", plrT);