first commit
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class EnemyVision : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
||||
public EnemyStateMachine stateMachine;
|
||||
public Transform player;
|
||||
|
||||
[Header("Vision")]
|
||||
public float viewRadius = 14f;
|
||||
[Range(1f, 180f)]
|
||||
public float viewAngle = 65f;
|
||||
public LayerMask obstacleMask;
|
||||
public LayerMask targetMask;
|
||||
public float eyeHeight = 1.4f;
|
||||
public float standingDetectionDelay = 0.12f;
|
||||
public float crouchDetectionDelay = 0.35f;
|
||||
|
||||
private bool hadLineOfSight;
|
||||
private float visibleTimer;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
stateMachine = stateMachine != null ? stateMachine : GetComponent<EnemyStateMachine>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
AcquirePlayer();
|
||||
if (player == null || stateMachine == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool canSeePlayer = CanSeePlayer(out Vector3 eyePosition, out Vector3 targetPosition, out Color debugColor);
|
||||
Debug.DrawRay(eyePosition, targetPosition - eyePosition, debugColor);
|
||||
|
||||
if (canSeePlayer)
|
||||
{
|
||||
PlayerStealth stealth = player.GetComponent<PlayerStealth>();
|
||||
float requiredTime = stealth != null && stealth.IsCrouching ? crouchDetectionDelay : standingDetectionDelay;
|
||||
visibleTimer += Time.deltaTime;
|
||||
|
||||
if (visibleTimer >= requiredTime)
|
||||
{
|
||||
hadLineOfSight = true;
|
||||
stateMachine.OnPlayerDetected(player.position);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
visibleTimer = 0f;
|
||||
if (hadLineOfSight)
|
||||
{
|
||||
hadLineOfSight = false;
|
||||
stateMachine.OnPlayerLost();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float GetViewRadiusForCurrentTarget()
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
return viewRadius;
|
||||
}
|
||||
|
||||
PlayerStealth stealth = player.GetComponent<PlayerStealth>();
|
||||
return viewRadius * (stealth != null ? stealth.VisibilityMultiplier : 1f);
|
||||
}
|
||||
|
||||
private bool CanSeePlayer(out Vector3 eyePosition, out Vector3 targetPosition, out Color debugColor)
|
||||
{
|
||||
eyePosition = transform.position + Vector3.up * eyeHeight;
|
||||
targetPosition = player.position + Vector3.up * 0.9f;
|
||||
debugColor = Color.gray;
|
||||
|
||||
float effectiveRadius = GetViewRadiusForCurrentTarget();
|
||||
Vector3 directionToPlayer = targetPosition - eyePosition;
|
||||
float distanceToPlayer = directionToPlayer.magnitude;
|
||||
|
||||
if (distanceToPlayer > effectiveRadius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float angleToPlayer = Vector3.Angle(transform.forward, directionToPlayer);
|
||||
if (angleToPlayer > viewAngle * 0.5f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int combinedMask = obstacleMask | targetMask;
|
||||
if (Physics.Raycast(eyePosition, directionToPlayer.normalized, out RaycastHit hit, distanceToPlayer, combinedMask, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
// Если первым попался не игрок, значит между врагом и игроком есть укрытие или стена.
|
||||
bool isPlayerHit = hit.transform == player || hit.transform.IsChildOf(player);
|
||||
debugColor = isPlayerHit ? Color.green : Color.red;
|
||||
return isPlayerHit;
|
||||
}
|
||||
|
||||
debugColor = Color.red;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AcquirePlayer()
|
||||
{
|
||||
if (player != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject playerObject = GameObject.FindGameObjectWithTag("Player");
|
||||
if (playerObject != null)
|
||||
{
|
||||
player = playerObject.transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user