111 lines
3.1 KiB
C#
111 lines
3.1 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace Zenject.SpaceFighter
|
|
{
|
|
public class EnemyStateFollow : IEnemyState
|
|
{
|
|
readonly EnemyRotationHandler _rotationHandler;
|
|
readonly EnemyCommonSettings _commonSettings;
|
|
readonly Settings _settings;
|
|
readonly EnemyTunables _tunables;
|
|
readonly EnemyStateManager _stateManager;
|
|
readonly EnemyView _view;
|
|
readonly PlayerFacade _player;
|
|
|
|
bool _strafeRight;
|
|
float _lastStrafeChangeTime;
|
|
|
|
public EnemyStateFollow(
|
|
PlayerFacade player,
|
|
EnemyView view,
|
|
EnemyStateManager stateManager,
|
|
EnemyTunables tunables,
|
|
Settings settings,
|
|
EnemyCommonSettings commonSettings,
|
|
EnemyRotationHandler rotationHandler)
|
|
{
|
|
_rotationHandler = rotationHandler;
|
|
_commonSettings = commonSettings;
|
|
_settings = settings;
|
|
_tunables = tunables;
|
|
_stateManager = stateManager;
|
|
_view = view;
|
|
_player = player;
|
|
}
|
|
|
|
public void EnterState()
|
|
{
|
|
_strafeRight = Random.Range(0, 1) == 0;
|
|
_lastStrafeChangeTime = Time.realtimeSinceStartup;
|
|
}
|
|
|
|
public void ExitState()
|
|
{
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (_player.IsDead)
|
|
{
|
|
_stateManager.ChangeState(EnemyStates.Idle);
|
|
return;
|
|
}
|
|
|
|
var distanceToPlayer = (_player.Position - _view.Position).magnitude;
|
|
|
|
// Always look towards the player
|
|
_rotationHandler.DesiredLookDir = (_player.Position - _view.Position).normalized;
|
|
|
|
// Strafe back and forth over the given interval
|
|
// This helps avoiding being too easy a target
|
|
if (Time.realtimeSinceStartup - _lastStrafeChangeTime > _settings.StrafeChangeInterval)
|
|
{
|
|
_lastStrafeChangeTime = Time.realtimeSinceStartup;
|
|
_strafeRight = !_strafeRight;
|
|
}
|
|
|
|
if (distanceToPlayer < _commonSettings.AttackDistance)
|
|
{
|
|
_stateManager.ChangeState(EnemyStates.Attack);
|
|
}
|
|
}
|
|
|
|
public void FixedUpdate()
|
|
{
|
|
MoveTowardsPlayer();
|
|
Strafe();
|
|
}
|
|
|
|
void Strafe()
|
|
{
|
|
// Strafe to avoid getting hit too easily
|
|
if (_strafeRight)
|
|
{
|
|
_view.AddForce(_view.RightDir * _settings.StrafeMultiplier * _tunables.Speed);
|
|
}
|
|
else
|
|
{
|
|
_view.AddForce(-_view.RightDir * _settings.StrafeMultiplier * _tunables.Speed);
|
|
}
|
|
}
|
|
|
|
void MoveTowardsPlayer()
|
|
{
|
|
var playerDir = (_player.Position - _view.Position).normalized;
|
|
|
|
_view.AddForce(playerDir * _tunables.Speed);
|
|
}
|
|
|
|
[Serializable]
|
|
public class Settings
|
|
{
|
|
public float StrafeMultiplier;
|
|
public float StrafeChangeInterval;
|
|
public float TeleportNewDistance;
|
|
}
|
|
}
|
|
}
|
|
|