143 lines
4.8 KiB
C#
143 lines
4.8 KiB
C#
using System;
|
|
using SepCore.Definition;
|
|
using SepCore.Entity;
|
|
using SepCore.Simulation;
|
|
using UnityEngine;
|
|
using SepCore.Debugger;
|
|
|
|
namespace SepCore.Components
|
|
{
|
|
public class MovementComponent : MonoBehaviour
|
|
{
|
|
[SerializeField] private bool _isMoving;
|
|
[SerializeField] private Vector3 _direction;
|
|
[SerializeField] private Transform _cachedTransform;
|
|
[SerializeField] private bool _avoidEnemyOverlap;
|
|
[SerializeField] private float _enemyBodyRadius;
|
|
[SerializeField] private int _separationIterations;
|
|
|
|
public float Speed => (_speedBase + _movementStat.Value) * _movementStat.Percent;
|
|
public bool AvoidEnemyOverlap => _avoidEnemyOverlap;
|
|
public float EnemyBodyRadius => _enemyBodyRadius;
|
|
public int SeparationIterations => _separationIterations;
|
|
public bool IsMoving => _isMoving;
|
|
public Vector3 Direction => _direction;
|
|
public Transform CachedTransform => _cachedTransform;
|
|
[SerializeField] private float _speedBase;
|
|
|
|
private StatComponent _statComponent;
|
|
private Player _player;
|
|
private EnemyBase _enemy;
|
|
|
|
private StatProperty _movementStat;
|
|
private Action<modifier, bool> _movementStatCallback;
|
|
|
|
public void OnInit(float speed, Transform target, StatComponent statComponent = null,
|
|
bool avoidEnemyOverlap = false, float? enemyBodyRadius = null, int? separationIterations = null)
|
|
{
|
|
_speedBase = speed;
|
|
_cachedTransform = target;
|
|
_direction = Vector3.forward;
|
|
_avoidEnemyOverlap = avoidEnemyOverlap;
|
|
_enemyBodyRadius = Mathf.Max(0.01f, enemyBodyRadius ?? (GameEntry.Luban.Global.EnemyBodyRadius / 1000f));
|
|
_separationIterations = Mathf.Max(1, separationIterations ?? GameEntry.Luban.Global.EnemySeparationIterations);
|
|
|
|
TryGetComponent(out _player);
|
|
TryGetComponent(out _enemy);
|
|
|
|
_statComponent = statComponent;
|
|
if (_statComponent != null)
|
|
{
|
|
_movementStat = _statComponent.GetStat(StatType.MovementSpeed);
|
|
_movementStatCallback = (modifier, isApply) =>
|
|
{
|
|
_statComponent.UpdateStat(_movementStat, modifier, isApply);
|
|
SyncToSimulationWorld();
|
|
};
|
|
_statComponent.Subscribe(StatType.MovementSpeed, _movementStatCallback);
|
|
}
|
|
else
|
|
{
|
|
_movementStat = new StatProperty();
|
|
}
|
|
|
|
SyncToSimulationWorld();
|
|
}
|
|
|
|
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
|
{
|
|
SyncToSimulationWorld();
|
|
}
|
|
|
|
public void OnReset()
|
|
{
|
|
Transform transformToUnregister = _cachedTransform;
|
|
|
|
_speedBase = 0;
|
|
_cachedTransform = null;
|
|
_direction = Vector3.zero;
|
|
_isMoving = false;
|
|
_avoidEnemyOverlap = false;
|
|
_enemyBodyRadius = GameEntry.Luban.Global.EnemyBodyRadius / 1000f;
|
|
_separationIterations = GameEntry.Luban.Global.EnemySeparationIterations;
|
|
_player = null;
|
|
_enemy = null;
|
|
|
|
if (_statComponent != null)
|
|
{
|
|
_statComponent.Unsubscribe(StatType.MovementSpeed, _movementStatCallback);
|
|
_movementStatCallback = null;
|
|
}
|
|
|
|
_statComponent = null;
|
|
|
|
if (transformToUnregister != null)
|
|
{
|
|
GameEntry.SimulationWorld.UnregisterPlayerMovement(transformToUnregister);
|
|
}
|
|
}
|
|
|
|
public void SetMove(bool isMoving)
|
|
{
|
|
_isMoving = isMoving;
|
|
SyncToSimulationWorld();
|
|
}
|
|
|
|
public void SetDirection(Vector3 direction)
|
|
{
|
|
_direction = direction;
|
|
SyncToSimulationWorld();
|
|
}
|
|
|
|
private void SyncToSimulationWorld()
|
|
{
|
|
using (CustomProfilerMarker.Movement_Update.Auto())
|
|
{
|
|
if (_cachedTransform == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Vector3 direction = _direction;
|
|
direction.y = 0f;
|
|
if (direction.sqrMagnitude > Mathf.Epsilon)
|
|
{
|
|
direction.Normalize();
|
|
}
|
|
|
|
if (_player != null)
|
|
{
|
|
GameEntry.SimulationWorld.SyncPlayerMovementInput(_cachedTransform, _isMoving, direction, Speed);
|
|
return;
|
|
}
|
|
|
|
if (_enemy != null)
|
|
{
|
|
GameEntry.SimulationWorld.SyncEnemyMovementInput(_enemy.Id, _isMoving, direction, Speed,
|
|
_avoidEnemyOverlap, _enemyBodyRadius, _separationIterations);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|