如何控制相机移动时长?需求:5秒内从(0,0,0)移动至(100,0,100)
控制相机指定时长移动的实现方法
核心思路是通过时间进度驱动的线性插值(Lerp),让相机在设定时长内从起点平滑移动到终点。以下是具体实现方案:
通用原理
- 提前定义起点位置、终点位置和总移动时长
- 记录移动起始时间,每帧计算已流逝时间占总时长的比例(范围0~1)
- 用该比例对起点和终点位置做插值,得到相机当前帧的目标位置
- 当比例达到1时,将相机直接定位到终点,停止插值
伪代码示例
// 初始化参数 Vector3 startPos = (0, 0, 0) Vector3 targetPos = (100, 0, 100) float totalDuration = 5.0f float startTime = 当前时间戳 // 帧更新逻辑 void Update() { float elapsedTime = 当前时间戳 - startTime float progress = Math.Clamp(elapsedTime / totalDuration, 0, 1) Vector3 currentPos = Lerp(startPos, targetPos, progress) 设置相机位置为currentPos if (progress >= 1) { 停止移动更新 设置相机位置为targetPos // 确保精准到达 } }
Unity C# 实现示例
using UnityEngine; public class TimedCameraMove : MonoBehaviour { [SerializeField] private Vector3 startPosition = new(0, 0, 0); [SerializeField] private Vector3 targetPosition = new(100, 0, 100); [SerializeField] private float moveDuration = 5f; private float _startTime; private bool _isMoving; void Start() { StartMove(); } public void StartMove() { _startTime = Time.time; _isMoving = true; } void Update() { if (!_isMoving) return; float elapsedTime = Time.time - _startTime; float progress = Mathf.Clamp01(elapsedTime / moveDuration); transform.position = Vector3.Lerp(startPosition, targetPosition, progress); if (progress >= 1f) { _isMoving = false; transform.position = targetPosition; } } }
Unreal Engine C++ 实现示例
#include "Camera/CameraActor.h" #include "TimerManager.h" class ATimedCameraMove : public ACameraActor { GENERATED_BODY() public: ATimedCameraMove(); protected: virtual void BeginPlay() override; virtual void Tick(float DeltaTime) override; public: void StartCameraMove(FVector StartPos, FVector TargetPos, float Duration); private: FVector StartPosition; FVector TargetPosition; float MoveDuration; float StartTime; bool bIsMoving = false; }; // .cpp 文件实现 ATimedCameraMove::ATimedCameraMove() { PrimaryActorTick.bCanEverTick = true; } void ATimedCameraMove::BeginPlay() { Super::BeginPlay(); StartCameraMove(FVector(0,0,0), FVector(100,0,100), 5.0f); } void ATimedCameraMove::StartCameraMove(FVector StartPos, FVector TargetPos, float Duration) { StartPosition = StartPos; TargetPosition = TargetPos; MoveDuration = Duration; StartTime = GetWorld()->GetTimeSeconds(); bIsMoving = true; } void ATimedCameraMove::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (!bIsMoving) return; float ElapsedTime = GetWorld()->GetTimeSeconds() - StartTime; float Progress = FMath::Clamp(ElapsedTime / MoveDuration, 0.0f, 1.0f); FVector CurrentPos = FMath::Lerp(StartPosition, TargetPosition, Progress); SetActorLocation(CurrentPos); if (Progress >= 1.0f) { bIsMoving = false; SetActorLocation(TargetPosition); } }
额外优化建议
- 若需要平滑的启停效果,可使用缓动函数替换线性插值,比如Unity的
Mathf.SmoothStep或Unreal的FMath::SmoothStep,也可自定义缓动曲线 - 始终基于时间戳计算进度,避免帧率波动导致移动时长不准确
- 可增加打断逻辑,通过设置
_isMoving/bIsMoving为false随时终止移动
内容的提问来源于stack exchange,提问作者Steven1
相关产品推荐
相关产品推荐

