feat: enemies spawn in spawn zones and wander on a graph
This commit is contained in:
@@ -1,26 +1,65 @@
|
||||
using Pathfinding;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Pathfinding;
|
||||
using Pathfinding.Drawing;
|
||||
using UnityEngine;
|
||||
using Vector2 = UnityEngine.Vector2;
|
||||
using Vector3 = UnityEngine.Vector3;
|
||||
|
||||
namespace Reset.Units{
|
||||
public class EnemyPathfinding : MonoBehaviour, IUnitDirectionProvider{
|
||||
[RequireComponent(typeof(Seeker))]
|
||||
public class EnemyPathfinding : UnitComponent, IUnitDirectionProvider{
|
||||
public Vector2 Direction{ get; set; }
|
||||
|
||||
public Transform targetPosition;
|
||||
|
||||
|
||||
private Seeker seeker;
|
||||
|
||||
|
||||
public float nextWaypointDistance = 3;
|
||||
private int currentWaypoint;
|
||||
|
||||
public Path path;
|
||||
public bool reachedEndOfPath;
|
||||
|
||||
private Coroutine wanderPathCoroutine;
|
||||
|
||||
public void Start(){
|
||||
seeker = GetComponent<Seeker>();
|
||||
// If you are writing a 2D game you should remove this line
|
||||
// and use the alternative way to move sugggested further below.
|
||||
|
||||
Enemy thisEnemy = (Unit as Enemy);
|
||||
|
||||
if (thisEnemy.relatedSpawner){
|
||||
seeker.graphMask = GraphMask.FromGraph(thisEnemy.relatedSpawner.relatedGraph);
|
||||
} else {
|
||||
Debug.LogWarning("Creating a graph for a singular enemy is not yet implemented. Graph mask not set on this unit.", transform);
|
||||
}
|
||||
|
||||
StartCoroutine(WaitForWanderPath());
|
||||
}
|
||||
|
||||
seeker.StartPath(transform.position, targetPosition.position, OnPathComplete);
|
||||
IEnumerator WaitForWanderPath(){
|
||||
yield return new WaitForSeconds(Random.Range(1f, 7f));
|
||||
StartWanderPath();
|
||||
|
||||
wanderPathCoroutine = null;
|
||||
}
|
||||
|
||||
void StartWanderPath(){
|
||||
Enemy thisEnemy = (Unit as Enemy);
|
||||
Vector3 pathTargetPos = transform.position;
|
||||
|
||||
if (thisEnemy.relatedSpawner) {
|
||||
pathTargetPos = thisEnemy.relatedSpawner.transform.position;
|
||||
}
|
||||
|
||||
Vector3 randomizedDestination = new Vector3(
|
||||
Random.Range(-thisEnemy.relatedSpawner.radius, thisEnemy.relatedSpawner.radius),
|
||||
0f,
|
||||
Random.Range(-thisEnemy.relatedSpawner.radius, thisEnemy.relatedSpawner.radius)
|
||||
);
|
||||
|
||||
pathTargetPos += randomizedDestination;
|
||||
|
||||
seeker.StartPath(transform.position, pathTargetPos, OnPathComplete);
|
||||
}
|
||||
|
||||
public void OnPathComplete(Path p){
|
||||
@@ -40,6 +79,7 @@ namespace Reset.Units{
|
||||
reachedEndOfPath = false;
|
||||
// The distance to the next waypoint in the path
|
||||
float distanceToWaypoint;
|
||||
|
||||
while (true) {
|
||||
// If you want maximum performance you can check the squared distance instead to get rid of a
|
||||
// square root calculation. But that is outside the scope of this tutorial.
|
||||
@@ -52,22 +92,29 @@ namespace Reset.Units{
|
||||
// Set a status variable to indicate that the agent has reached the end of the path.
|
||||
// You can use this to trigger some special code if your game requires that.
|
||||
reachedEndOfPath = true;
|
||||
|
||||
if (wanderPathCoroutine == null) {
|
||||
wanderPathCoroutine = StartCoroutine(WaitForWanderPath());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the direction to the direction handler interface
|
||||
if (currentWaypoint + 1 == path.vectorPath.Count) {
|
||||
Direction = (path.vectorPath[currentWaypoint] - transform.position).ToVector2();
|
||||
Direction = Vector3.ClampMagnitude(Direction, 1f);
|
||||
} else {
|
||||
Direction = (path.vectorPath[currentWaypoint] - transform.position).normalized.ToVector2();
|
||||
}
|
||||
|
||||
// Slow down smoothly upon approaching the end of the path
|
||||
// This value will smoothly go from 1 to 0 as the agent approaches the last waypoint in the path.
|
||||
var speedFactor = reachedEndOfPath ? Mathf.Sqrt(distanceToWaypoint / nextWaypointDistance) : 1f;
|
||||
|
||||
// Direction to the next waypoint
|
||||
// Normalize it so that it has a length of 1 world unit
|
||||
Vector3 dirToPoint = (path.vectorPath[currentWaypoint] - transform.position).normalized * speedFactor;
|
||||
|
||||
Direction = dirToPoint.ToVector2();
|
||||
// Draw an indicator for the path
|
||||
Draw.ingame.SolidCircle(path.vectorPath[currentWaypoint] + Vector3.up * .02f, Vector3.up, .3f);
|
||||
Draw.ingame.Arrow(transform.position, transform.position + Direction.ToVector3(), Vector3.up, .3f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user