Danro/Assets/Scripts/Entities/Props/Platforms/ShiftingPlatform.cs
Danil Iarosh bd57b74d8b level 1-3 updates, bug fixes etc
- улучшил структуру уровня 1-3
- пофиксил баг с застреванием персонажа на уровне 1-3
- пофиксил баг с прилипанием игрока к платформе сбоку
- изменил логику платформ
- добавил больше динамичности в уровень 1-3
2025-11-28 16:48:31 +03:00

112 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Linq;
using RR.Game2D.Core;
using UnityEngine;
namespace RR.Game2D.Entities.Platforms
{
public class ShiftingPlatform : MonoBehaviour
{
[Header("Настройки смещения платформы")]
[SerializeField] private Vector3 shiftAmount = new Vector3(0f, 2f, 0f);
[SerializeField] private float shiftDuration = 1f;
[SerializeField] private Direction2D shiftDirection = Direction2D.Down;
[Header("Прикрепление игрока")]
[SerializeField] private bool attachPlayer = true;
[Tooltip("Минимальный угол нормали контакта к вертикали для прикрепления (0.7 ≈ 45°)")]
[SerializeField, Range(0f, 1f)] private float normalThreshold = 0.7f;
private void OnCollisionEnter2D(Collision2D other)
{
if (!other.gameObject.CompareTag("Player")) return;
// Проверяем, что игрок стоит на верхней части платформы
if (attachPlayer && IsPlayerOnTop(other))
{
other.transform.SetParent(transform);
}
Vector3 shiftVector = shiftDirection switch
{
Direction2D.Down => Vector3.down * shiftAmount.y,
Direction2D.Left => Vector3.left * shiftAmount.x,
Direction2D.Right => Vector3.right * shiftAmount.x,
Direction2D.Up => Vector3.up * shiftAmount.y,
_ => Vector3.zero
};
StopAllCoroutines();
StartCoroutine(ShiftPlatform(shiftVector));
}
private void OnCollisionStay2D(Collision2D other)
{
if (!attachPlayer) return;
if (!other.gameObject.CompareTag("Player")) return;
// Если игрок уже прикреплён, но больше не на верхней части - отсоединяем
if (other.transform.parent == transform && !IsPlayerOnTop(other))
{
other.transform.SetParent(null);
}
// Если игрок не прикреплён, но теперь на верхней части - прикрепляем
else if (other.transform.parent != transform && IsPlayerOnTop(other))
{
other.transform.SetParent(transform);
}
}
private void OnCollisionExit2D(Collision2D other)
{
if (!other.gameObject.CompareTag("Player")) return;
if (attachPlayer && other.transform.parent == transform)
{
other.transform.SetParent(null);
}
Vector3 shiftVector = shiftDirection switch
{
Direction2D.Down => Vector3.up * shiftAmount.y,
Direction2D.Left => Vector3.right * shiftAmount.x,
Direction2D.Right => Vector3.left * shiftAmount.x,
Direction2D.Up => Vector3.down * shiftAmount.y,
_ => Vector3.zero
};
StopAllCoroutines();
StartCoroutine(ShiftPlatform(shiftVector));
}
/// <summary>
/// Проверяет, находится ли игрок на верхней части платформы
/// </summary>
/// <param name="collision">Данные о столкновении</param>
/// <returns>True, если игрок стоит сверху</returns>
private bool IsPlayerOnTop(Collision2D collision)
{
// Проверяем нормали всех контактных точек
// Нормаль направлена от другого объекта (игрока) к платформе,
// поэтому если игрок сверху, нормаль будет направлена вниз
return collision.contacts.Any(contact => Vector2.Dot(contact.normal, Vector2.down) > normalThreshold);
}
private IEnumerator ShiftPlatform(Vector3 shiftVector)
{
Vector3 initialPosition = transform.position;
Vector3 finalPosition = initialPosition + shiftVector;
float elapsedTime = 0f;
while (elapsedTime < shiftDuration)
{
transform.position = Vector3.Lerp(initialPosition, finalPosition, (elapsedTime / shiftDuration));
elapsedTime += Time.deltaTime;
yield return null;
}
transform.position = finalPosition;
}
}
}