← Назад к вопросам
Реализовать следование камеры за персонажем
1.0 Junior🔥 271 комментариев
#C# и ООП#Unity Core#Физика и математика
Условие
Реализуйте плавное следование камеры за персонажем.
Требования
- Камера следует за целью с небольшим отставанием
- Настраиваемый offset и дистанция
- Плавное вращение при повороте персонажа
- Ограничение по осям для 2D платформера
- Опция look ahead в направлении движения
Варианты
- Cinemachine подход
- Собственная реализация с Lerp
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение: Следование камеры за персонажем
Архитектура
Хорошая система слежения камеры критична для комфортного геймплея. Рассмотрю оба варианта: с Cinemachine (встроенный инструмент) и ручную реализацию с Lerp.
Вариант 1: Собственная реализация (рекомендуется)
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
[Header("Target")]
[SerializeField] private Transform target;
[SerializeField] private bool useLocalPosition = false;
[Header("Offset")]
[SerializeField] private Vector3 offset = new Vector3(0, 2, -5);
[Header("Smoothing")]
[SerializeField] private float smoothSpeed = 5f;
[SerializeField] private float rotationSmoothSpeed = 5f;
[Header("Look Ahead")]
[SerializeField] private bool useLookAhead = false;
[SerializeField] private float lookAheadDistance = 5f;
[SerializeField] private Rigidbody targetRigidbody;
[Header("Constraints")]
[SerializeField] private bool constrainX = false;
[SerializeField] private Vector2 constrainXRange = new Vector2(-10f, 10f);
[SerializeField] private bool constrainY = false;
[SerializeField] private Vector2 constrainYRange = new Vector2(0f, 10f);
private Vector3 desiredPosition;
private Vector3 velocity = Vector3.zero;
void LateUpdate()
{
if (target == null) return;
UpdateCameraPosition();
UpdateCameraRotation();
}
private void UpdateCameraPosition()
{
Vector3 targetPosition = target.position;
// Look ahead в направлении движения
if (useLookAhead && targetRigidbody != null)
{
Vector3 moveVel = targetRigidbody.velocity;
if (moveVel.magnitude > 0.1f)
{
targetPosition += moveVel.normalized * lookAheadDistance;
}
}
// Желаемая позиция камеры
desiredPosition = targetPosition + offset;
// SmoothDamp для плавного движения
transform.position = Vector3.SmoothDamp(
transform.position,
desiredPosition,
ref velocity,
1f / smoothSpeed
);
// Ограничения
ApplyConstraints();
}
private void UpdateCameraRotation()
{
Vector3 direction = target.position - transform.position;
if (direction.magnitude > 0.01f)
{
Quaternion desiredRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Lerp(
transform.rotation,
desiredRotation,
Time.deltaTime * rotationSmoothSpeed
);
}
}
private void ApplyConstraints()
{
Vector3 pos = transform.position;
if (constrainX) pos.x = Mathf.Clamp(pos.x, constrainXRange.x, constrainXRange.y);
if (constrainY) pos.y = Mathf.Clamp(pos.y, constrainYRange.x, constrainYRange.y);
transform.position = pos;
}
public void SetTarget(Transform newTarget) => target = newTarget;
}
Вариант 2: Для 2D платформеров
using UnityEngine;
public class CameraFollow2D : MonoBehaviour
{
[Header("Target")]
[SerializeField] private Transform target;
[Header("Settings")]
[SerializeField] private float smoothSpeed = 5f;
[SerializeField] private Vector2 offset = new Vector2(0, 1);
[Header("Look Ahead")]
[SerializeField] private bool useLookAhead = true;
[SerializeField] private float lookAheadAmount = 2f;
[Header("Bounds")]
[SerializeField] private Vector2 minBounds = new Vector2(-10, -10);
[SerializeField] private Vector2 maxBounds = new Vector2(10, 10);
[SerializeField] private bool useConstraints = true;
private Vector3 velocity = Vector3.zero;
private float playerDirection = 1f;
void LateUpdate()
{
if (target == null) return;
// Определяем направление
if (target.TryGetComponent<Rigidbody2D>(out var rb2d))
{
if (rb2d.velocity.x != 0)
playerDirection = Mathf.Sign(rb2d.velocity.x);
}
UpdatePosition();
}
private void UpdatePosition()
{
Vector3 targetPos = target.position;
if (useLookAhead)
targetPos.x += lookAheadAmount * playerDirection;
targetPos.x += offset.x;
targetPos.y += offset.y;
targetPos.z = transform.position.z;
// SmoothDamp
transform.position = Vector3.SmoothDamp(
transform.position,
targetPos,
ref velocity,
1f / smoothSpeed
);
// Ограничения
if (useConstraints)
{
Vector3 pos = transform.position;
pos.x = Mathf.Clamp(pos.x, minBounds.x, maxBounds.x);
pos.y = Mathf.Clamp(pos.y, minBounds.y, maxBounds.y);
transform.position = pos;
}
}
}
Вариант 3: С Cinemachine
using UnityEngine;
using Cinemachine;
public class CinemachineSetup : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private CinemachineVirtualCamera virtualCamera;
void Start()
{
virtualCamera = GetComponent<CinemachineVirtualCamera>();
virtualCamera.Follow = target;
virtualCamera.LookAt = target;
var composer = virtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
if (composer != null)
{
composer.m_TrackedObjectOffset = new Vector3(0, 1, 0);
composer.m_CameraDistance = 5f;
composer.m_XDamping = 1f;
composer.m_YDamping = 0.5f;
}
}
}
Ключевые параметры
- Smoothing Speed — как быстро ловит камера (5-10 оптимально)
- Offset — смещение от персонажа (Vector3)
- Look Ahead — предугадывает движение
- Constraints — границы сценария
- Rotation Speed — скорость поворота
Рекомендации
Для простых игр используй Вариант 1 или 2 (собственная реализация). Для крупных проектов с множеством камер используй Cinemachine. Параметр smoothSpeed 5-10 обычно оптимален.
Эта система обеспечивает плавное, профессиональное следование камеры.