added: enemy target acquisition, better pathfinding, moved combat reference to unit
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
35
Assets/Scripts/Units/Graph Tasks/CheckIfSpawnmate.cs
Normal file
35
Assets/Scripts/Units/Graph Tasks/CheckIfSpawnmate.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Reset.Units {
|
||||
[Category("Reset/Units")]
|
||||
[Description("Returns true if this unit is in the same spawn group as the provided value.")]
|
||||
public class CheckIfSpawnmate : ConditionTask<Enemy>{
|
||||
protected override string info{ get => $"{target} is spawnmate"; }
|
||||
|
||||
public BBParameter<GameObject> target;
|
||||
|
||||
//Use for initialization. This is called only once in the lifetime of the task.
|
||||
//Return null if init was successfull. Return an error string otherwise
|
||||
protected override string OnInit(){
|
||||
return null;
|
||||
}
|
||||
|
||||
//Called whenever the condition gets enabled.
|
||||
protected override void OnEnable() {
|
||||
|
||||
}
|
||||
|
||||
//Called whenever the condition gets disabled.
|
||||
protected override void OnDisable() {
|
||||
|
||||
}
|
||||
|
||||
//Called once per frame while the condition is active.
|
||||
//Return whether the condition is success or failure.
|
||||
protected override bool OnCheck(){
|
||||
return agent.relatedSpawner.enemies.Contains(target.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 847ff34f59879c844b597a39884f5fe8
|
||||
64
Assets/Scripts/Units/Graph Tasks/SetWanderingPath.cs
Normal file
64
Assets/Scripts/Units/Graph Tasks/SetWanderingPath.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using Pathfinding;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Reset.Units {
|
||||
|
||||
[Category("Reset/Pathfinding")]
|
||||
[Description("Set the agent's current path to a wandering path.")]
|
||||
public class SetWanderingPath : ActionTask<UnitPathfinding> {
|
||||
|
||||
//Use for initialization. This is called only once in the lifetime of the task.
|
||||
//Return null if init was successfull. Return an error string otherwise
|
||||
protected override string OnInit() {
|
||||
return null;
|
||||
}
|
||||
|
||||
//This is called once each time the task is enabled.
|
||||
//Call EndAction() to mark the action as finished, either in success or failure.
|
||||
//EndAction can be called from anywhere.
|
||||
protected override void OnExecute(){
|
||||
Enemy thisEnemy = agent.Unit as Enemy;
|
||||
Vector3 pathTargetPos = agent.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;
|
||||
|
||||
agent.seeker.StartPath(agent.transform.position, pathTargetPos, OnPathComplete);
|
||||
|
||||
EndAction(true);
|
||||
}
|
||||
|
||||
public void OnPathComplete(Path p){
|
||||
if (!p.error) {
|
||||
agent.AssignNewPath(p);
|
||||
}
|
||||
}
|
||||
|
||||
//Called once per frame while the action is active.
|
||||
protected override void OnUpdate() {
|
||||
|
||||
}
|
||||
|
||||
//Called when the task is disabled.
|
||||
protected override void OnStop() {
|
||||
|
||||
}
|
||||
|
||||
//Called when the task is paused.
|
||||
protected override void OnPause() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8b7661016b47ae4e9137833e7111460
|
||||
@@ -24,6 +24,14 @@ namespace Reset.Units{
|
||||
get{ if (!_graph) { _graph = GetComponent<GraphOwner>(); } return _graph; }
|
||||
}
|
||||
|
||||
private UnitCombat _combat;
|
||||
internal UnitCombat Combat{
|
||||
get {
|
||||
if (_combat == null) { _combat = GetComponent<UnitCombat>(); }
|
||||
return _combat;
|
||||
}
|
||||
}
|
||||
|
||||
// Debug and Gizmos
|
||||
public NetworkVariable<FixedString64Bytes> graphStateAsString;
|
||||
|
||||
|
||||
@@ -9,18 +9,16 @@ using Vector3 = UnityEngine.Vector3;
|
||||
|
||||
namespace Reset.Units{
|
||||
[RequireComponent(typeof(Seeker))]
|
||||
public class EnemyPathfinding : UnitComponent, IUnitDirectionProvider{
|
||||
public class UnitPathfinding : UnitComponent, IUnitDirectionProvider{
|
||||
public Vector2 Direction{ get; set; }
|
||||
|
||||
private Seeker seeker;
|
||||
|
||||
public Seeker seeker;
|
||||
|
||||
public float nextWaypointDistance = 3;
|
||||
private int currentWaypoint;
|
||||
|
||||
public Path path;
|
||||
public bool reachedEndOfPath;
|
||||
|
||||
private Coroutine wanderPathCoroutine;
|
||||
|
||||
public void Start(){
|
||||
seeker = GetComponent<Seeker>();
|
||||
@@ -32,37 +30,9 @@ namespace Reset.Units{
|
||||
} 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){
|
||||
public void AssignNewPath(Path p){
|
||||
if (!p.error) {
|
||||
path = p;
|
||||
// Reset the waypoint counter so that we start to move towards the first point in the path
|
||||
@@ -71,6 +41,10 @@ namespace Reset.Units{
|
||||
}
|
||||
|
||||
public void Update(){
|
||||
FollowCurrentPath();
|
||||
}
|
||||
|
||||
private void FollowCurrentPath(){
|
||||
if (path == null) {
|
||||
// We have no path to follow yet, so don't do anything
|
||||
return;
|
||||
@@ -92,10 +66,6 @@ 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;
|
||||
}
|
||||
@@ -111,7 +81,7 @@ namespace Reset.Units{
|
||||
} 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);
|
||||
2
Assets/Scripts/Units/UnitPathfinding.cs.meta
Normal file
2
Assets/Scripts/Units/UnitPathfinding.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a72dabd280fe71488a78596bd852afc
|
||||
Reference in New Issue
Block a user