127 lines
4.4 KiB
C#
127 lines
4.4 KiB
C#
using Code.DI;
|
|
using Code.Input;
|
|
using UnityEngine;
|
|
|
|
namespace Code.Gameplay.Camera
|
|
{
|
|
public class CameraController : MonoBehaviour
|
|
{
|
|
[Header("Settings")]
|
|
[SerializeField] private float rotationSpeed = 300f;
|
|
[SerializeField] private float rotationSharpness = 10f;
|
|
[SerializeField] private float followSharpness = 10f;
|
|
[SerializeField] private float minVerticalAngle = -90f;
|
|
[SerializeField] private float maxVerticalAngle = 90f;
|
|
[SerializeField] private float defaultVerticalAngle = 0f;
|
|
|
|
[Header("Target")]
|
|
[SerializeField] private Transform followTransform;
|
|
|
|
private UnityEngine.Camera _camera;
|
|
private Vector3 _currentFollowPosition;
|
|
private Vector3 _planarDirection;
|
|
private float _targetVerticalAngle;
|
|
private IInputService _inputService;
|
|
|
|
private void Awake()
|
|
{
|
|
_camera = GetComponent<UnityEngine.Camera>();
|
|
if (_camera == null)
|
|
{
|
|
Debug.LogError("CameraController requires a Camera component!");
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
Initialize();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_inputService = FindFirstObjectByType<DIContainer>().Resolve<IInputService>();
|
|
}
|
|
|
|
private void Initialize()
|
|
{
|
|
_targetVerticalAngle = Mathf.Clamp(defaultVerticalAngle, minVerticalAngle, maxVerticalAngle);
|
|
_planarDirection = followTransform != null ? followTransform.forward : Vector3.forward;
|
|
_currentFollowPosition = followTransform != null ? followTransform.position : Vector3.zero;
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (followTransform != null)
|
|
{
|
|
UpdateCamera(Time.deltaTime, GetLookInput());
|
|
}
|
|
}
|
|
|
|
private void UpdateCamera(float deltaTime, Vector3 lookInput)
|
|
{
|
|
// Handle rotation
|
|
Quaternion targetRotation = HandleRotation(deltaTime, lookInput);
|
|
|
|
// Handle position
|
|
HandlePosition(deltaTime, targetRotation);
|
|
}
|
|
|
|
private Quaternion HandleRotation(float deltaTime, Vector3 lookInput)
|
|
{
|
|
// Horizontal rotation
|
|
Quaternion horizontalRotation = Quaternion.Euler(Vector3.up * (lookInput.x * rotationSpeed));
|
|
_planarDirection = horizontalRotation * _planarDirection;
|
|
Quaternion planarRotation = Quaternion.LookRotation(_planarDirection, followTransform.up);
|
|
|
|
// Vertical rotation
|
|
_targetVerticalAngle -= lookInput.y * rotationSpeed;
|
|
_targetVerticalAngle = Mathf.Clamp(_targetVerticalAngle, minVerticalAngle, maxVerticalAngle);
|
|
Quaternion verticalRotation = Quaternion.Euler(_targetVerticalAngle, 0, 0);
|
|
|
|
// Combine and apply
|
|
Quaternion targetRotation = planarRotation * verticalRotation;
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, deltaTime * rotationSharpness);
|
|
|
|
return targetRotation;
|
|
}
|
|
|
|
private void HandlePosition(float deltaTime, Quaternion targetRotation)
|
|
{
|
|
_currentFollowPosition = Vector3.Lerp(
|
|
_currentFollowPosition,
|
|
followTransform.position,
|
|
1f - Mathf.Exp(-followSharpness * deltaTime)
|
|
);
|
|
|
|
transform.position = _currentFollowPosition;
|
|
}
|
|
|
|
private Vector3 GetLookInput()
|
|
{
|
|
// Получите здесь ваш инпут (например, из Input System)
|
|
// Это пример для стандартного инпута:
|
|
return _inputService.MoveInput;
|
|
}
|
|
|
|
// Публичные методы для получения данных
|
|
public Quaternion GetCameraRotation()
|
|
{
|
|
return transform.rotation;
|
|
}
|
|
|
|
public Vector3 GetPlanarDirection()
|
|
{
|
|
return _planarDirection;
|
|
}
|
|
|
|
// Метод для установки цели следования
|
|
public void SetFollowTransform(Transform target)
|
|
{
|
|
followTransform = target;
|
|
if (target != null)
|
|
{
|
|
_currentFollowPosition = target.position;
|
|
_planarDirection = target.forward;
|
|
}
|
|
}
|
|
}
|
|
} |