Files
vampire-like/Assets/GameMain/Scripts/Runtime/Components/MovementComponent.cs
T
2026-09-18 21:43:22 +08:00

155 lines
5.4 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 => _statComponent != null ? _statComponent.GetStatValue(StatType.MoveSpeed) : _speedBase;
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 Action<StatType, float> _onStatChangedAction;
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;
float defaultRadius = GameEntry.Luban != null && GameEntry.Luban.IsReady
? GameEntry.Luban.Global.EnemyBodyRadius / 1000f
: 0.5f;
int defaultIterations = GameEntry.Luban != null && GameEntry.Luban.IsReady
? GameEntry.Luban.Global.EnemySeparationIterations
: 4;
_enemyBodyRadius = Mathf.Max(0.01f, enemyBodyRadius ?? defaultRadius);
_separationIterations = Mathf.Max(1, separationIterations ?? defaultIterations);
TryGetComponent(out _player);
TryGetComponent(out _enemy);
_statComponent = statComponent;
if (_statComponent != null)
{
_statComponent.Pipeline.SetBaseValue(StatType.MoveSpeed, speed);
_onStatChangedAction = OnStatChanged;
_statComponent.Pipeline.OnStatChanged += _onStatChangedAction;
}
SyncToSimulationWorld();
}
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
SyncToSimulationWorld();
}
public void OnReset()
{
Transform transformToUnregister = _cachedTransform;
float defaultRadius = GameEntry.Luban != null && GameEntry.Luban.IsReady
? GameEntry.Luban.Global.EnemyBodyRadius / 1000f
: 0.5f;
int defaultIterations = GameEntry.Luban != null && GameEntry.Luban.IsReady
? GameEntry.Luban.Global.EnemySeparationIterations
: 4;
_speedBase = 0;
_cachedTransform = null;
_direction = Vector3.zero;
_isMoving = false;
_avoidEnemyOverlap = false;
_enemyBodyRadius = defaultRadius;
_separationIterations = defaultIterations;
_player = null;
_enemy = null;
if (_statComponent != null && _onStatChangedAction != null)
{
_statComponent.Pipeline.OnStatChanged -= _onStatChangedAction;
_onStatChangedAction = null;
}
_statComponent = null;
if (transformToUnregister != null && GameEntry.SimulationWorld != 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 || GameEntry.SimulationWorld == 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);
}
}
}
private void OnStatChanged(StatType statType, float newValue)
{
if (statType == StatType.MoveSpeed)
{
SyncToSimulationWorld();
}
}
}
}