Not a member of GistPad yet?
Sign Up,
it unlocks many cool features!
- using UdonSharp;
- using UnityEngine;
- using VRC.SDKBase;
- public class WaterSystem : UdonSharpBehaviour
- {
- [Header("--- Настройки синевы ---")]
- // Смещение синего экрана относительно центра триггера (уровень глаз)
- [SerializeField] private float offset = -0.4f;
- // Прозрачность/плотность тумана под водой (от 0 до 1)
- [SerializeField] [Range(0f, 1f)] private float waterDensity = 1.0f;
- [Header("--- Настройки плавания ---")]
- // Скорость, с которой персонаж взлетает/всплывает вверх
- [SerializeField] private float swimSpeed = 2.5f;
- // Расстояние от глаз до плеч аватара (чтобы не вылетать из воды слишком высоко)
- [SerializeField] private float shouldersOffset = 0.22f;
- // Внутренние технические переменные
- private VRCPlayerApi localPlayer; // Ссылка на самого игрока
- private bool inWater = false; // Находится ли игрок в воде прямо сейчас
- private float mobileVerticalInput = 0f; // Сюда мы будем записывать движение мобильного джойстика
- void Start()
- {
- // Находим локального игрока (того, кто запустил игру на своем устройстве)
- localPlayer = Networking.LocalPlayer;
- }
- public override void OnPlayerTriggerEnter(VRCPlayerApi player)
- {
- // Проверяем, что в триггер вошел именно наш (локальный) игрок
- if (player != null && player.isLocal)
- {
- inWater = true;
- // Настройка физики: включаем "невесомость" и замедляем бег/ходьбу
- player.SetGravityStrength(0.01f);
- player.SetWalkSpeed(2f); // Скорость шага в воде
- player.SetRunSpeed(2.5f); // Скорость бега в воде
- }
- }
- public override void OnPlayerTriggerExit(VRCPlayerApi player)
- {
- // Проверяем, что триггер покинул именно наш (локальный) игрок
- if (player != null && player.isLocal)
- {
- inWater = false;
- // Полностью отключаем подводный туман экрана
- RenderSettings.fog = false;
- RenderSettings.fogDensity = 0f;
- // Возвращаем стандартные настройки физики для суши
- player.SetGravityStrength(1.0f);
- player.SetWalkSpeed(4f);
- player.SetRunSpeed(4f);
- }
- }
- public override void OnInputMoveVertical(float value, VRCInputMethod inputMethod)
- {
- // VRChat сам передает сюда значение джойстика:
- // 1.0 — джойстик зажат полностью вперед, -1.0 — полностью назад
- mobileVerticalInput = value;
- }
- void Update()
- {
- // Если игрок на суше или ссылка на него пропала — ничего не делаем
- if (!inWater || localPlayer == null) return;
- // Находим текущую высоту головы (глаз) игрока по Y
- float headY = localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).position.y;
- // Вычисляем верхнюю границу воды с учетом нашего смещения offset
- float triggerTopY = transform.position.y + offset;
- // Вычисляем высоту плеч аватара
- float shouldersY = headY - shouldersOffset;
- // --- ЛОГИКА СИНЕВЫ ЭКРАНА (ВИЗУАЛ) ---
- if (headY < triggerTopY)
- {
- // Если глаза под водой: включаем туман
- RenderSettings.fog = true;
- RenderSettings.fogDensity = waterDensity;
- }
- else
- {
- // Если глаза над водой: выключаем туман
- RenderSettings.fog = false;
- RenderSettings.fogDensity = 0f;
- }
- // --- ЛОГИКА ПЛАВАНИЯ (ФИЗИКА) ---
- // Получаем направление взгляда игрока (куда повернута голова)
- Vector3 lookDir = localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).rotation * Vector3.forward;
- // Условие для мобилок и ПК: зажат джойстик/кнопка "Вперед"
- bool isMovingForward = mobileVerticalInput > 0.1f;
- if (isMovingForward)
- {
- // ПЛЫВЕМ ВВЕРХ: если смотрим вверх (lookDir.y > 0.2) и плечи еще под водой
- if (lookDir.y > 0.2f && shouldersY < triggerTopY)
- {
- Vector3 vel = localPlayer.GetVelocity();
- vel.y = swimSpeed; // Задаем скорость движения вверх
- localPlayer.SetVelocity(vel);
- }
- // ПЛЫВЕМ ВНИЗ: если смотрим вниз (lookDir.y < -0.2)
- else if (lookDir.y < -0.2f)
- {
- Vector3 vel = localPlayer.GetVelocity();
- vel.y = -swimSpeed; // Задаем скорость движения вниз (отрицательная)
- localPlayer.SetVelocity(vel);
- }
- }
- // Защита от "взлета": если плечи поднялись выше воды, обнуляем вертикальную скорость
- if (shouldersY >= triggerTopY)
- {
- Vector3 vel = localPlayer.GetVelocity();
- if (vel.y > 0)
- {
- vel.y = 0;
- localPlayer.SetVelocity(vel);
- }
- }
- } // Закрывается метод Update()
- } // Закрывается класс WaterSystem
RAW Paste Data
Copied
