diff --git a/Game/CourierOld/Assets/Code/Configs/CharacterCameraConfig.cs b/Game/CourierOld/Assets/Code/Configs/CharacterCameraConfig.cs new file mode 100644 index 0000000..d1eeba3 --- /dev/null +++ b/Game/CourierOld/Assets/Code/Configs/CharacterCameraConfig.cs @@ -0,0 +1,34 @@ +using Code.Gameplay.Character.Core; +using UnityEngine; + +namespace Code.Configs +{ + [CreateAssetMenu(fileName = "CharacterCameraConfig", menuName = "Config/CharacterCameraConfig")] + public class CharacterCameraConfig : ScriptableObject + { + public float + // Расстояния от персонажа до камеры + defaultDistance = 6f, // Стандартное расстояние камеры от цели + minDistance = 3f, // Минимальное расстояние при зуме + maxDistance = 10f, // Максимальное расстояние при зуме + + // Скорость зума камеры + distanceMovementSpeed = 5f, // Множитель скорости изменения дистанции при зуме + + // Скорость поворота камеры + rotationSpeed = 0.3f, // Множитель скорости вращения камеры + + // Скорость интерполяции текущее -> целевое вращение + rotationSharpness = 100f, // Коэффициент плавности вращения камеры (чем выше - тем резче) + + // Резкость следования камеры за целью + followSharpness = 100f, // Коэффициент плавности следования за движущейся целью (чем выше - тем резче) + + // Углы наклона камеры + minVerticalAngle = -70f, // Минимальный угол наклона камеры (вниз) + maxVerticalAngle = 70f, // Максимальный угол наклона камеры (вверх) + defaultVerticalAngle = 10f; // Стандартный угол наклона камеры + + public CameraMode defaultCameraMode = CameraMode.MainMenu; // Текущий режим камеры + } +} \ No newline at end of file diff --git a/Game/CourierOld/Assets/Code/Configs/CharacterCameraConfig.cs.meta b/Game/CourierOld/Assets/Code/Configs/CharacterCameraConfig.cs.meta new file mode 100644 index 0000000..773ba0a --- /dev/null +++ b/Game/CourierOld/Assets/Code/Configs/CharacterCameraConfig.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 72fbf590e5fd4747acfdd32eb26bba3a +timeCreated: 1761637489 \ No newline at end of file diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Camera/CharacterCamera.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Camera/CharacterCamera.cs index 9278075..4d59bb2 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Camera/CharacterCamera.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Camera/CharacterCamera.cs @@ -1,5 +1,7 @@ using System; using Code.Gameplay.Character.Core; +using Code.StaticData; +using Reflex.Attributes; using UnityEngine; namespace Code.Gameplay.Character.Camera @@ -13,38 +15,39 @@ namespace Code.Gameplay.Character.Camera */ public class CharacterCamera : MonoBehaviour { - [SerializeField] + // Значения теперь берутся из конфига private float // Расстояния от персонажа до камеры - defaultDistance = 6f, // Стандартное расстояние камеры от цели - minDistance = 3f, // Минимальное расстояние при зуме - maxDistance = 10f, // Максимальное расстояние при зуме + _defaultDistance, // Стандартное расстояние камеры от цели + _minDistance, // Минимальное расстояние при зуме + _maxDistance, // Максимальное расстояние при зуме // Скорость зума камеры - distanceMovementSpeed = 5f, // Множитель скорости изменения дистанции при зуме + _distanceMovementSpeed, // Множитель скорости изменения дистанции при зуме // Скорость поворота камеры - rotationSpeed = 0.3f, // Множитель скорости вращения камеры + _rotationSpeed, // Множитель скорости вращения камеры // Скорость интерполяции текущее -> целевое вращение - rotationSharpness = 100f, // Коэффициент плавности вращения камеры (чем выше - тем резче) + _rotationSharpness, // Коэффициент плавности вращения камеры (чем выше - тем резче) // Резкость следования камеры за целью - followSharpness = 100f, // Коэффициент плавности следования за движущейся целью (чем выше - тем резче) + _followSharpness, // Коэффициент плавности следования за движущейся целью (чем выше - тем резче) // Углы наклона камеры - minVerticalAngle = -70f, // Минимальный угол наклона камеры (вниз) - maxVerticalAngle = 70f, // Максимальный угол наклона камеры (вверх) - defaultVerticalAngle = 10f; // Стандартный угол наклона камеры + _minVerticalAngle, // Минимальный угол наклона камеры (вниз) + _maxVerticalAngle, // Максимальный угол наклона камеры (вверх) + _defaultVerticalAngle; // Стандартный угол наклона камеры - // Текущий режим работы камеры - // Трансформ объекта, за которым следует камера (для 1st-person: уровень глаз) private Transform _followTransform; // Позиция следования: текущая сглаженная позиция и горизонтальное направление камеры private Vector3 _currentFollowPosition; + // Позиция следования по умолчанию (для меню) + private readonly Vector3 _defaultFollowPosition = Vector3.zero; + // Целевой вертикальный угол камеры (наклон вверх/вниз) private float _targetVerticalAngle; @@ -53,24 +56,53 @@ namespace Code.Gameplay.Character.Camera // Исходные значения дистанции для восстановления после FirstPerson режима private float _originalDefaultDistance, _originalMinDistance, _originalMaxDistance; - + // Свойства для доступа к важным данным камеры извне public Vector3 PlanarDirection { get; private set; } // Горизонтальное направление камеры - public CameraMode CurrentMode { get; private set; } = CameraMode.ThirdPerson; // Текущий режим камеры + public CameraMode CurrentMode { get; private set; } + + [Inject] private IStaticDataService _staticDataService; + + // Загрузка конфига для камеры + private void LoadConfig() + { + var config = _staticDataService.CharacterCameraConfig; + + // Загрузка значений из конфигов + _defaultDistance = config.defaultDistance; + _minDistance = config.minDistance; + _maxDistance = config.maxDistance; + _distanceMovementSpeed = config.distanceMovementSpeed; + _rotationSpeed = config.rotationSpeed; + _rotationSharpness = config.rotationSharpness; + _followSharpness = config.followSharpness; + _minVerticalAngle = config.minVerticalAngle; + _maxVerticalAngle = config.maxVerticalAngle; + _defaultVerticalAngle = config.defaultVerticalAngle; + CurrentMode = config.defaultCameraMode; + + // Обеспечиваем корректные значения дистанции и угла + _defaultDistance = Mathf.Clamp(_defaultDistance, _minDistance, _maxDistance); + _defaultVerticalAngle = Mathf.Clamp(_defaultVerticalAngle, _minVerticalAngle, _maxVerticalAngle); + // Сохраняем оригинальные значения для восстановления + _originalDefaultDistance = _defaultDistance; + _originalMinDistance = _minDistance; + _originalMaxDistance = _maxDistance; + + _currentDistance = _defaultDistance; + _targetDistance = _currentDistance; + _targetVerticalAngle = _defaultVerticalAngle; + PlanarDirection = Vector3.forward; // Начальное направление - вперед по оси Z + + _currentFollowPosition = _defaultFollowPosition; + } + // Инициализация камеры при создании private void Awake() { - // Сохраняем исходные значения дистанции для восстановления - _originalDefaultDistance = defaultDistance; - _originalMinDistance = minDistance; - _originalMaxDistance = maxDistance; - - _currentDistance = defaultDistance; - _targetDistance = _currentDistance; - _targetVerticalAngle = 0f; - PlanarDirection = Vector3.forward; // Начальное направление - вперед по оси Z + LoadConfig(); } // Установка цели для следования камеры @@ -81,29 +113,21 @@ namespace Code.Gameplay.Character.Camera PlanarDirection = t.forward; // Начальное направление совпадает с направлением цели } - // Валидация параметров в редакторе Unity - private void OnValidate() - { - // Обеспечиваем корректные значения дистанции и угла - defaultDistance = Mathf.Clamp(defaultDistance, minDistance, maxDistance); - defaultVerticalAngle = Mathf.Clamp(defaultVerticalAngle, minVerticalAngle, maxVerticalAngle); - } - // Обработка вращения камеры на основе пользовательского ввода private void HandleRotationInput(float deltaTime, Vector3 rotationInput, out Quaternion targetRotation) { // Вращение вокруг вертикальной оси (горизонтальный поворот) - var rotationFromInput = Quaternion.Euler(_followTransform.up * (rotationInput.x * rotationSpeed)); + var rotationFromInput = Quaternion.Euler(_followTransform.up * (rotationInput.x * _rotationSpeed)); PlanarDirection = rotationFromInput * PlanarDirection; var planarRotation = Quaternion.LookRotation(PlanarDirection, _followTransform.up); // Вращение вокруг горизонтальной оси (вертикальный наклон) - _targetVerticalAngle -= rotationInput.y * rotationSpeed; - _targetVerticalAngle = Math.Clamp(_targetVerticalAngle, minVerticalAngle, maxVerticalAngle); + _targetVerticalAngle -= rotationInput.y * _rotationSpeed; + _targetVerticalAngle = Math.Clamp(_targetVerticalAngle, _minVerticalAngle, _maxVerticalAngle); var verticalRotation = Quaternion.Euler(_targetVerticalAngle, 0, 0); // Интерполяция к целевому вращению для плавности - targetRotation = Quaternion.Slerp(transform.rotation, planarRotation * verticalRotation, deltaTime * rotationSharpness); + targetRotation = Quaternion.Slerp(transform.rotation, planarRotation * verticalRotation, deltaTime * _rotationSharpness); // Применение финального вращения transform.rotation = targetRotation; @@ -116,12 +140,12 @@ namespace Code.Gameplay.Character.Camera if (CurrentMode != CameraMode.FirstPerson) { // Обновление целевой дистанции на основе ввода зума - _targetDistance += zoomInput * distanceMovementSpeed; - _targetDistance = Mathf.Clamp(_targetDistance, minDistance, maxDistance); + _targetDistance += zoomInput * _distanceMovementSpeed; + _targetDistance = Mathf.Clamp(_targetDistance, _minDistance, _maxDistance); } // Плавное следование за целью с использованием экспоненциального сглаживания - _currentFollowPosition = Vector3.Lerp(_currentFollowPosition, _followTransform.position, 1f - Mathf.Exp(-followSharpness * deltaTime)); + _currentFollowPosition = Vector3.Lerp(_currentFollowPosition, _followTransform.position, 1f - Mathf.Exp(-_followSharpness * deltaTime)); // Вычисление целевой позиции камеры с учетом текущего режима Vector3 targetPosition; @@ -139,7 +163,7 @@ namespace Code.Gameplay.Character.Camera // Плавное изменение текущей дистанции к целевой (только для ThirdPerson) if (CurrentMode != CameraMode.FirstPerson) { - _currentDistance = Mathf.Lerp(_currentDistance, _targetDistance, 1f - Mathf.Exp(-distanceMovementSpeed * deltaTime)); + _currentDistance = Mathf.Lerp(_currentDistance, _targetDistance, 1f - Mathf.Exp(-_distanceMovementSpeed * deltaTime)); } // Установка финальной позиции камеры @@ -149,11 +173,11 @@ namespace Code.Gameplay.Character.Camera // Основной метод обновления камеры, вызываемый извне каждый кадр public void UpdateWithInput(float deltaTime, float zoomInput, Vector3 rotationInput) { - // Проверка наличия цели для следования - if (!_followTransform) return; + // Проверка наличия цели для следования и проверка на режим главного меню + if (!_followTransform || CurrentMode == CameraMode.MainMenu) return; // Обработка ввода и позиционирования - HandleRotationInput(deltaTime, rotationInput, out Quaternion targetRotation); + HandleRotationInput(deltaTime, rotationInput, out var targetRotation); HandlePosition(deltaTime, zoomInput, targetRotation); } @@ -174,20 +198,21 @@ namespace Code.Gameplay.Character.Camera { case CameraMode.FirstPerson: // В FirstPerson режиме дистанция всегда равна 0 - minDistance = 0f; - maxDistance = 0f; - defaultDistance = 0f; + _minDistance = 0f; + _maxDistance = 0f; + _defaultDistance = 0f; _targetDistance = 0f; _currentDistance = 0f; break; case CameraMode.ThirdPerson: // Восстанавливаем исходные значения дистанции - minDistance = _originalMinDistance; - maxDistance = _originalMaxDistance; - defaultDistance = _originalDefaultDistance; - _targetDistance = defaultDistance; + _minDistance = _originalMinDistance; + _maxDistance = _originalMaxDistance; + _defaultDistance = _originalDefaultDistance; + _targetDistance = _defaultDistance; break; // Заготовка на будущее (если понадобится) + case CameraMode.MainMenu: case CameraMode.Static: case CameraMode.Cinematic: default: diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Core/CameraMode.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Core/CameraMode.cs index 92dfaf6..6c86d84 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Core/CameraMode.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Core/CameraMode.cs @@ -9,6 +9,7 @@ namespace Code.Gameplay.Character.Core */ public enum CameraMode { + MainMenu, Static, FirstPerson, ThirdPerson, diff --git a/Game/CourierOld/Assets/Code/StaticData/IStaticDataService.cs b/Game/CourierOld/Assets/Code/StaticData/IStaticDataService.cs index 6b4561c..213466d 100644 --- a/Game/CourierOld/Assets/Code/StaticData/IStaticDataService.cs +++ b/Game/CourierOld/Assets/Code/StaticData/IStaticDataService.cs @@ -8,5 +8,6 @@ namespace Code.StaticData void Load(); InputConfig InputConfig { get; } AppConfig AppConfig { get; } + CharacterCameraConfig CharacterCameraConfig { get; } } } \ No newline at end of file diff --git a/Game/CourierOld/Assets/Code/StaticData/StaticDataService.cs b/Game/CourierOld/Assets/Code/StaticData/StaticDataService.cs index 33a1b9a..2b7af3a 100644 --- a/Game/CourierOld/Assets/Code/StaticData/StaticDataService.cs +++ b/Game/CourierOld/Assets/Code/StaticData/StaticDataService.cs @@ -8,11 +8,13 @@ namespace Code.StaticData { public AppConfig AppConfig { get; private set; } public InputConfig InputConfig { get; private set; } + public CharacterCameraConfig CharacterCameraConfig { get; private set; } public void Load() { InputConfig = Resources.Load(string.Format(StringPaths.ConfigSingle, "App", "InputConfig")); AppConfig = Resources.Load(string.Format(StringPaths.ConfigSingle, "App", "AppConfig")); + CharacterCameraConfig = Resources.Load(string.Format(StringPaths.ConfigSingle, "App", "CharacterCameraConfig")); } } } \ No newline at end of file diff --git a/Game/CourierOld/Assets/Resources/Configs/App/CharacterCameraConfig.asset b/Game/CourierOld/Assets/Resources/Configs/App/CharacterCameraConfig.asset new file mode 100644 index 0000000..c85fd84 --- /dev/null +++ b/Game/CourierOld/Assets/Resources/Configs/App/CharacterCameraConfig.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 72fbf590e5fd4747acfdd32eb26bba3a, type: 3} + m_Name: CharacterCameraConfig + m_EditorClassIdentifier: Assembly-CSharp::Code.Configs.CharacterCameraConfig + defaultDistance: 6 + minDistance: 3 + maxDistance: 10 + distanceMovementSpeed: 5 + rotationSpeed: 0.3 + rotationSharpness: 100 + followSharpness: 100 + minVerticalAngle: -70 + maxVerticalAngle: 70 + defaultVerticalAngle: 10 + defaultCameraMode: 0 diff --git a/Game/CourierOld/Assets/Resources/Configs/App/CharacterCameraConfig.asset.meta b/Game/CourierOld/Assets/Resources/Configs/App/CharacterCameraConfig.asset.meta new file mode 100644 index 0000000..b58b958 --- /dev/null +++ b/Game/CourierOld/Assets/Resources/Configs/App/CharacterCameraConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6938984fc7d25285abb4922dd46d9272 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Game/CourierOld/Packages/manifest.json b/Game/CourierOld/Packages/manifest.json index 876c157..8e3a006 100644 --- a/Game/CourierOld/Packages/manifest.json +++ b/Game/CourierOld/Packages/manifest.json @@ -5,15 +5,15 @@ "com.unity.ai.navigation": "2.0.9", "com.unity.collab-proxy": "2.10.0", "com.unity.ide.rider": "3.0.38", - "com.unity.ide.visualstudio": "2.0.23", + "com.unity.ide.visualstudio": "2.0.25", "com.unity.inputsystem": "1.14.2", "com.unity.multiplayer.center": "1.0.0", "com.unity.render-pipelines.universal": "17.2.0", "com.unity.test-framework": "1.6.0", "com.unity.timeline": "1.8.9", - "com.unity.toolchain.linux-x86_64": "2.0.10", + "com.unity.toolchain.linux-x86_64": "2.0.11", "com.unity.ugui": "2.0.0", - "com.unity.visualscripting": "1.9.7", + "com.unity.visualscripting": "1.9.9", "com.unity.modules.accessibility": "1.0.0", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", diff --git a/Game/CourierOld/Packages/packages-lock.json b/Game/CourierOld/Packages/packages-lock.json index 2f4354a..bafd245 100644 --- a/Game/CourierOld/Packages/packages-lock.json +++ b/Game/CourierOld/Packages/packages-lock.json @@ -7,7 +7,7 @@ "dependencies": { "com.unity.localization": "1.0.0" }, - "hash": "bd1d662b53cff58b86c2cef02b284a52ce964cae" + "hash": "dfa901c9eeef09febe0dfb2f2a52319ea532747f" }, "com.gustavopsantos.reflex": { "version": "https://github.com/gustavopsantos/reflex.git?path=/Assets/Reflex/#13.0.2", @@ -87,11 +87,11 @@ "url": "https://packages.unity.com" }, "com.unity.ide.visualstudio": { - "version": "2.0.23", + "version": "2.0.25", "depth": 0, "source": "registry", "dependencies": { - "com.unity.test-framework": "1.1.9" + "com.unity.test-framework": "1.1.31" }, "url": "https://packages.unity.com" }, @@ -268,7 +268,7 @@ "url": "https://packages.unity.com" }, "com.unity.toolchain.linux-x86_64": { - "version": "2.0.10", + "version": "2.0.11", "depth": 0, "source": "registry", "dependencies": { @@ -287,7 +287,7 @@ } }, "com.unity.visualscripting": { - "version": "1.9.7", + "version": "1.9.9", "depth": 0, "source": "registry", "dependencies": {