Unity_lab3/Unity3_lab/Assets/Scripts/BallController.cs
savilokirill@gmail.com 8946e6704d шлейф
более менее работает
2025-11-12 01:57:52 +03:00

170 lines
6.5 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 UnityEngine;
public class BallController : MonoBehaviour
{
[Header("Ссылки")]
private Transform currentPlatform = null;
[Header("Настройки Движения")]
[SerializeField] private float moveSpeed = 15f;
[SerializeField] private float airControlSpeed = 5f;
[SerializeField] private float jumpForce = 7f;
[SerializeField] private float trampolineBounceForce = 1.5f; // Множитель для отскока от батута
private Rigidbody rb;
private bool isGrounded;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
}
void Update()
{
HandleJumpInput();
}
void FixedUpdate()
{
isGrounded = false;
HandleMovement();
}
public bool IsGrounded
{
get { return isGrounded; }
}
// --- Логика Управления Движением (Без изменений) ---
private void HandleMovement()
{
float moveX = Input.GetAxis("Horizontal");
float moveZ = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveX, 0.0f, moveZ).normalized;
if (currentPlatform != null && isGrounded)
{
// Случай 1: Прилипли к ДВИЖУЩЕЙСЯ платформе (двигаем относительно родителя)
if (movement.magnitude > 0.01f)
{
Vector3 localMovement = currentPlatform.TransformDirection(movement) * moveSpeed * Time.fixedDeltaTime;
rb.MovePosition(rb.position + localMovement);
}
}
else
{
// Случай 2: На СТАТИЧНОЙ земле, БАТУТЕ или в воздухе (используем AddForce)
float currentSpeed = isGrounded ? moveSpeed : airControlSpeed;
rb.AddForce(movement * currentSpeed, ForceMode.Acceleration);
}
}
private void HandleJumpInput()
{
if (Input.GetButtonDown("Jump") && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false;
transform.SetParent(null);
currentPlatform = null;
}
}
// --- Логика Взаимодействия и Прилипания (Обновленная) ---
private void OnCollisionEnter(Collision collision)
{
CheckIfGrounded(collision);
// 1. Проверяем, является ли объект БАТУТОМ
if (collision.gameObject.CompareTag("Trampoline"))
{
// Случай 3: БАТУТ -> Моментальный отскок
// Если мы уже прилипли к чему-то, отлипаем
if (currentPlatform != null)
{
transform.SetParent(null);
currentPlatform = null;
}
// *** ГЛАВНОЕ ИЗМЕНЕНИЕ: Находим нормаль к поверхности ***
// Получаем нормаль к поверхности в точке столкновения.
// Это и есть направление, перпендикулярное поверхности.
Vector3 surfaceNormal = Vector3.up;
if (collision.contacts.Length > 0)
{
// Используем нормаль первого контакта для определения направления отскока
surfaceNormal = collision.contacts[0].normal;
}
// Применяем сильный импульс в направлении нормали
// Сбрасываем текущую вертикальную скорость шарика, чтобы отскок был одинаковым
// Для более физически корректного отскока, мы можем очистить всю скорость
rb.linearVelocity = Vector3.zero;
// Применяем силу, направленную строго по нормали поверхности.
rb.AddForce(surfaceNormal * jumpForce * trampolineBounceForce, ForceMode.Impulse);
return; // Завершаем проверку, это батут, прилипать не нужно
}
// 2. Проверяем на ДВИЖУЩУЮСЯ ПЛАТФОРМУ
MovingPlatform platformScript = collision.gameObject.GetComponent<MovingPlatform>();
if (platformScript != null)
{
// Случай 1: ДВИЖУЩАЯСЯ ПЛАТФОРМА -> Прилипаем
if (isGrounded)
{
transform.SetParent(collision.transform);
currentPlatform = collision.transform;
}
}
else
{
// Случай 2: СТАТИЧЕСКАЯ ЗЕМЛЯ (обычная неподвижная платформа)
// Гарантируем, что мы не прилипли, если это не MovingPlatform
if (currentPlatform != null)
{
transform.SetParent(null);
currentPlatform = null;
}
}
}
private void OnCollisionStay(Collision collision)
{
CheckIfGrounded(collision);
}
private void OnCollisionExit(Collision collision)
{
// Логика отлипания: Сбрасываем родителя только если покидаем MovingPlatform
MovingPlatform platformScript = collision.gameObject.GetComponent<MovingPlatform>();
if (platformScript != null)
{
transform.SetParent(null);
currentPlatform = null;
}
// Для батута и статики отлипание уже произошло в OnCollisionEnter
}
// Вспомогательный метод для проверки земли
private void CheckIfGrounded(Collision collision)
{
if (isGrounded) return;
if (collision.contacts.Length > 0)
{
Vector3 normal = collision.contacts[0].normal;
if (normal.y > 0.7f) // ~45 градусов
{
isGrounded = true;
}
}
}
}