added: enemy target acquisition, better pathfinding, moved combat reference to unit

This commit is contained in:
Chris
2025-11-10 16:06:21 -05:00
parent a6182cd066
commit fa810bf970
14 changed files with 398 additions and 63 deletions

View File

@@ -1,8 +1,15 @@
using UnityEngine;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Reset.Units{
public class EnemyCombat : UnitCombat, IUnitTargetProvider{
public GameObject target;
public GameObject UnitTarget => target;
[Button]
public void SetNewTarget(GameObject newTarget){
Unit.Graph.SendEvent("New Target Set");
target = newTarget;
}
}
}

View File

@@ -1,121 +0,0 @@
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{
[RequireComponent(typeof(Seeker))]
public class EnemyPathfinding : UnitComponent, IUnitDirectionProvider{
public Vector2 Direction{ get; set; }
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>();
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());
}
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){
if (!p.error) {
path = p;
// Reset the waypoint counter so that we start to move towards the first point in the path
currentWaypoint = 0;
}
}
public void Update(){
if (path == null) {
// We have no path to follow yet, so don't do anything
return;
}
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.
distanceToWaypoint = Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]);
if (distanceToWaypoint < nextWaypointDistance) {
// Check if there is another waypoint or if we have reached the end of the path
if (currentWaypoint + 1 < path.vectorPath.Count) {
currentWaypoint++;
} else {
// 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();
}
// 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);
}
}
}

View File

@@ -32,7 +32,7 @@ namespace Reset.Units{
relatedGraph.collision.diameter = 3f;
AstarPath.active.Scan(relatedGraph);
GetComponent<ProceduralGraphMover>().graph = relatedGraph;
}
@@ -59,6 +59,39 @@ namespace Reset.Units{
// Update is called once per frame
void Update(){
Draw.WireCylinder(transform.position, transform.position + Vector3.up * 7f, radius);
if (PlayerIsInRange()) {
SetPlayerAsTarget();
}
}
GameObject PlayerIsInRange(){
// TODO: Make compatible with all players
Vector3 playerPos = PlayerManager.Player.transform.position;
// Skip checking and return null/false if the player is nowhere near the spawn
if (Vector3.Distance(playerPos, transform.position) < radius * 1.5f) {
return null;
}
// If they are in range, check if the player is close enough to either an enemy or the spawn center
if (Vector3.Distance(playerPos, transform.position) < radius * .33f) {
return PlayerManager.Player;
}
foreach (GameObject thisEnemy in enemies) {
if (Vector3.Distance(playerPos, thisEnemy.transform.position) < radius / 2f) {
return PlayerManager.Player;
}
}
return null;
}
void SetPlayerAsTarget(){
foreach (GameObject thisEnemy in enemies) {
thisEnemy.GetComponent<EnemyCombat>().SetNewTarget(PlayerManager.Player);
}
}
}