Danro-Jump/Assets/Scripts/Runtime/Gameplay/Platforms/MovingPlatformBehaviour.cs
Danil Iarosh 1f6884c5ac Build gameplay systems and service settings
Подробные изменения:
- Добавлены и доработаны модальные окна главного меню, сервисные настройки, шаблоны UI Toolkit и единый scene-flow сервис для переходов между сценами.
- Расширена gameplay-архитектура: сессия забега, HUD, спавн контента платформ, collectible-предметы, оборудование, хрупкие и движущиеся платформы.
- Добавлена база противников: типы спавна, патрулирование, процедурный спавнер, правила размещения через ScriptableObject-сложности и убийство врагов прыжком сверху.
- Исправлены смерть и respawn игрока, финальный GameOver, отскоки от врагов, пружин и boost-предметов, а также проход сквозь врагов при усиленном подъеме.
- Проведен рефакторинг взаимодействия систем: общий landing context, единые правила player-contact, NonLazy gameplay session, fail-fast installer и централизованный выбор точек спавна.
- Обновлены сцены, prefab-ассеты, difficulty stages, ресурсы главного меню, настройки проекта, roadmap и аппаратная COM-интеграция.
- Добавлены ассеты летучей мыши, врагов, collectibles, TextMesh Pro, ProjectContext и gameplay UI.

Проверки:
- dotnet build .\\Assembly-CSharp.csproj --no-restore
- Unity validation ключевых gameplay/UI/scene-flow скриптов
- Unity Console после force refresh без ошибок
2026-05-27 16:34:51 +03:00

135 lines
4.2 KiB
C#

using UnityEngine;
namespace DanroJump.Gameplay
{
/// <summary>
/// Двигает платформу по синусоиде вокруг позиции спавна.
/// </summary>
public sealed class MovingPlatformBehaviour : MonoBehaviour, IPlatformLifecycle
{
[SerializeField] private Vector2 localMoveAxis = Vector2.right;
[SerializeField] [Min(0f)] private float amplitude = 1.25f;
[SerializeField] [Min(0.01f)] private float cycleDuration = 2.5f;
[SerializeField] private bool useSpawnIndexOffset = true;
private const float TwoPi = Mathf.PI * 2f;
private Transform cachedTransform;
private Rigidbody2D body;
private Vector3 basePosition;
private Vector2 normalizedMoveAxis = Vector2.right;
private float angularSpeed;
private float phaseOffset;
private void Awake()
{
cachedTransform = transform;
body = GetComponent<Rigidbody2D>();
RefreshMoveAxis();
}
#if UNITY_EDITOR
private void OnValidate()
{
RefreshMoveAxis();
}
#endif
/// <summary>
/// Обновляет позицию платформы вдоль локальной оси движения.
/// </summary>
private void Update()
{
if (body != null)
{
return;
}
MoveVisual(Time.time);
}
private void FixedUpdate()
{
if (body == null)
{
return;
}
body.MovePosition((Vector2)CalculatePosition(Time.fixedTime));
}
/// <summary>
/// Двигает visual-only платформу через Transform.
/// </summary>
private void MoveVisual(float time)
{
if (amplitude <= 0f || cycleDuration <= 0f)
{
return;
}
cachedTransform.position = CalculatePosition(time);
}
/// <summary>
/// Рассчитывает позицию платформы на указанном времени симуляции.
/// </summary>
private Vector3 CalculatePosition(float time)
{
if (amplitude <= 0f || cycleDuration <= 0f)
{
return basePosition;
}
var phase = time * angularSpeed + phaseOffset * TwoPi;
return basePosition + (Vector3)(normalizedMoveAxis * (Mathf.Sin(phase) * amplitude));
}
/// <summary>
/// Запоминает позицию спавна при первом создании.
/// </summary>
public void Initialize(PlatformSpawnContext context)
{
ApplyContext(context);
}
/// <summary>
/// Запоминает новую позицию спавна при рецикле платформы.
/// </summary>
public void Recycle(PlatformSpawnContext context)
{
ApplyContext(context);
}
/// <summary>
/// Возвращает платформу в базовую позицию.
/// </summary>
public void ResetPlatform()
{
if (body != null)
{
body.position = (Vector2)basePosition;
return;
}
(cachedTransform != null ? cachedTransform : transform).position = basePosition;
}
/// <summary>
/// Применяет контекст спавна и рассчитывает фазу движения.
/// </summary>
private void ApplyContext(PlatformSpawnContext context)
{
RefreshMoveAxis();
basePosition = cachedTransform != null ? cachedTransform.position : transform.position;
phaseOffset = useSpawnIndexOffset ? context.SpawnIndex * 0.173f : 0f;
}
private void RefreshMoveAxis()
{
normalizedMoveAxis = localMoveAxis.sqrMagnitude > 0f ? localMoveAxis.normalized : Vector2.right;
angularSpeed = cycleDuration > 0f ? TwoPi / cycleDuration : 0f;
}
}
}