Files cleanup, added summoner code
This commit is contained in:
269
Assets/AI/_Archer/SA_FleeFromPlayer.cs
Normal file
269
Assets/AI/_Archer/SA_FleeFromPlayer.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
using Invector.vCharacterController.AI.FSMBehaviour;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ArcherEnemy
|
||||
{
|
||||
/// <summary>
|
||||
/// State action that makes archer flee/retreat from player
|
||||
/// Moves archer away from player while trying to maintain shooting distance
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Invector/FSM/Actions/Archer/Flee From Player")]
|
||||
public class SA_FleeFromPlayer : vStateAction
|
||||
{
|
||||
public override string categoryName => "Archer/Combat";
|
||||
public override string defaultName => "Flee From Player";
|
||||
|
||||
[Header("Flee Configuration")]
|
||||
[Tooltip("Desired safe distance from player")]
|
||||
public float safeDistance = 12f;
|
||||
|
||||
[Tooltip("How far to look ahead when fleeing")]
|
||||
public float fleeDistance = 5f;
|
||||
|
||||
[Tooltip("Check for obstacles when fleeing")]
|
||||
public bool avoidObstacles = true;
|
||||
|
||||
[Tooltip("Layers considered as obstacles")]
|
||||
public LayerMask obstacleMask = -1;
|
||||
|
||||
[Tooltip("Number of directions to try when finding flee path")]
|
||||
public int directionSamples = 8;
|
||||
|
||||
[Header("Movement")]
|
||||
[Tooltip("Movement speed multiplier (uses AI's speed)")]
|
||||
[Range(0.5f, 2f)]
|
||||
public float speedMultiplier = 1.2f;
|
||||
|
||||
[Tooltip("Make archer sprint while fleeing")]
|
||||
public bool useSprint = true;
|
||||
|
||||
[Header("Rotation")]
|
||||
[Tooltip("Keep facing player while backing away")]
|
||||
public bool facePlayer = true;
|
||||
|
||||
[Tooltip("Rotation speed when facing player (degrees/sec)")]
|
||||
public float turnSpeed = 180f;
|
||||
|
||||
[Header("Debug")]
|
||||
[Tooltip("Enable debug logging")]
|
||||
public bool enableDebug = false;
|
||||
|
||||
[Tooltip("Show flee direction gizmos")]
|
||||
public bool showGizmos = true;
|
||||
|
||||
private Vector3 currentFleeDirection;
|
||||
private Transform currentTarget;
|
||||
|
||||
public override void DoAction(vIFSMBehaviourController fsmBehaviour, vFSMComponentExecutionType executionType = vFSMComponentExecutionType.OnStateUpdate)
|
||||
{
|
||||
if (executionType == vFSMComponentExecutionType.OnStateEnter)
|
||||
{
|
||||
OnEnter(fsmBehaviour);
|
||||
}
|
||||
else if (executionType == vFSMComponentExecutionType.OnStateUpdate)
|
||||
{
|
||||
OnUpdate(fsmBehaviour);
|
||||
}
|
||||
else if (executionType == vFSMComponentExecutionType.OnStateExit)
|
||||
{
|
||||
OnExit(fsmBehaviour);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnter(vIFSMBehaviourController fsmBehaviour)
|
||||
{
|
||||
currentTarget = GetTarget(fsmBehaviour);
|
||||
|
||||
if (currentTarget == null)
|
||||
{
|
||||
if (enableDebug) Debug.LogWarning("[SA_FleeFromPlayer] No target found!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate initial flee direction
|
||||
currentFleeDirection = CalculateFleeDirection(fsmBehaviour);
|
||||
|
||||
// Set AI to sprint if enabled
|
||||
var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI;
|
||||
if (aiController != null && useSprint)
|
||||
{
|
||||
}
|
||||
|
||||
if (enableDebug) Debug.Log("[SA_FleeFromPlayer] Started fleeing from player");
|
||||
}
|
||||
|
||||
private void OnUpdate(vIFSMBehaviourController fsmBehaviour)
|
||||
{
|
||||
if (currentTarget == null)
|
||||
{
|
||||
currentTarget = GetTarget(fsmBehaviour);
|
||||
if (currentTarget == null) return;
|
||||
}
|
||||
|
||||
// Recalculate flee direction periodically
|
||||
currentFleeDirection = CalculateFleeDirection(fsmBehaviour);
|
||||
|
||||
// Move in flee direction
|
||||
MoveInDirection(fsmBehaviour, currentFleeDirection);
|
||||
|
||||
// Face player while fleeing if enabled
|
||||
if (facePlayer)
|
||||
{
|
||||
RotateTowardsPlayer(fsmBehaviour);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExit(vIFSMBehaviourController fsmBehaviour)
|
||||
{
|
||||
// Reset AI speed
|
||||
var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI;
|
||||
if (aiController != null)
|
||||
{
|
||||
}
|
||||
|
||||
if (enableDebug) Debug.Log("[SA_FleeFromPlayer] Stopped fleeing");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the best direction to flee
|
||||
/// </summary>
|
||||
private Vector3 CalculateFleeDirection(vIFSMBehaviourController fsmBehaviour)
|
||||
{
|
||||
Vector3 archerPos = fsmBehaviour.transform.position;
|
||||
Vector3 playerPos = currentTarget.position;
|
||||
|
||||
// Basic flee direction: away from player
|
||||
Vector3 awayFromPlayer = (archerPos - playerPos).normalized;
|
||||
|
||||
// If not avoiding obstacles, return simple direction
|
||||
if (!avoidObstacles)
|
||||
{
|
||||
return awayFromPlayer;
|
||||
}
|
||||
|
||||
// Try to find clear path
|
||||
Vector3 bestDirection = awayFromPlayer;
|
||||
float bestScore = EvaluateDirection(archerPos, awayFromPlayer, playerPos);
|
||||
|
||||
// Sample multiple directions around the flee vector
|
||||
for (int i = 0; i < directionSamples; i++)
|
||||
{
|
||||
float angle = (360f / directionSamples) * i;
|
||||
Vector3 testDirection = Quaternion.Euler(0f, angle, 0f) * awayFromPlayer;
|
||||
float score = EvaluateDirection(archerPos, testDirection, playerPos);
|
||||
|
||||
if (score > bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
bestDirection = testDirection;
|
||||
}
|
||||
}
|
||||
|
||||
return bestDirection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates how good a flee direction is (higher = better)
|
||||
/// </summary>
|
||||
private float EvaluateDirection(Vector3 from, Vector3 direction, Vector3 playerPos)
|
||||
{
|
||||
float score = 0f;
|
||||
|
||||
// Check if path is clear
|
||||
Ray ray = new Ray(from + Vector3.up * 0.5f, direction);
|
||||
bool isBlocked = Physics.Raycast(ray, fleeDistance, obstacleMask, QueryTriggerInteraction.Ignore);
|
||||
|
||||
if (!isBlocked)
|
||||
{
|
||||
score += 10f; // Big bonus for clear path
|
||||
}
|
||||
|
||||
// Prefer directions that move away from player
|
||||
Vector3 awayFromPlayer = (from - playerPos).normalized;
|
||||
float alignment = Vector3.Dot(direction, awayFromPlayer);
|
||||
score += alignment * 5f;
|
||||
|
||||
// Check destination height (avoid running off cliffs)
|
||||
Vector3 destination = from + direction * fleeDistance;
|
||||
if (Physics.Raycast(destination + Vector3.up * 2f, Vector3.down, 5f, obstacleMask))
|
||||
{
|
||||
score += 3f; // Bonus for having ground
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves archer in specified direction
|
||||
/// </summary>
|
||||
private void MoveInDirection(vIFSMBehaviourController fsmBehaviour, Vector3 direction)
|
||||
{
|
||||
var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI;
|
||||
|
||||
if (aiController == null) return;
|
||||
|
||||
// Calculate destination point
|
||||
Vector3 destination = fsmBehaviour.transform.position + direction * fleeDistance;
|
||||
|
||||
// Use Invector's AI movement
|
||||
aiController.MoveTo(destination);
|
||||
|
||||
// Apply speed multiplier
|
||||
var motor = aiController as Invector.vCharacterController.AI.vSimpleMeleeAI_Controller;
|
||||
if (motor != null)
|
||||
{
|
||||
// This would need to be adapted to your specific Invector version
|
||||
// The goal is to make the archer move faster while fleeing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates archer to face player while backing away
|
||||
/// </summary>
|
||||
private void RotateTowardsPlayer(vIFSMBehaviourController fsmBehaviour)
|
||||
{
|
||||
if (currentTarget == null) return;
|
||||
|
||||
Vector3 directionToPlayer = (currentTarget.position - fsmBehaviour.transform.position);
|
||||
directionToPlayer.y = 0f;
|
||||
|
||||
if (directionToPlayer.sqrMagnitude > 0.001f)
|
||||
{
|
||||
Quaternion targetRotation = Quaternion.LookRotation(directionToPlayer);
|
||||
fsmBehaviour.transform.rotation = Quaternion.RotateTowards(
|
||||
fsmBehaviour.transform.rotation,
|
||||
targetRotation,
|
||||
turnSpeed * Time.deltaTime
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private Transform GetTarget(vIFSMBehaviourController fsmBehaviour)
|
||||
{
|
||||
// Try through AI controller
|
||||
var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI;
|
||||
if (aiController != null && aiController.currentTarget != null)
|
||||
return aiController.currentTarget.transform;
|
||||
|
||||
// Fallback - find player
|
||||
GameObject player = GameObject.FindGameObjectWithTag("Player");
|
||||
return player?.transform;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (!showGizmos || !Application.isPlaying) return;
|
||||
|
||||
// Draw current flee direction
|
||||
if (currentFleeDirection != Vector3.zero)
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
// This would need the archer's position to draw properly
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user