Godot Version
4.6
Question
When the camera is following the character, the screen shakes when the character stops moving. I’m not sure why this is happening.
This is the script attached to the CharacterBody3D
CharacterBody3D
- CollisionShape3D
- MeshInstance3D
using Godot;
public partial class PlayerMovement : CharacterBody3D
{
[Export] public float Speed = 6.0f;
[Export] public float JumpVelocity = 6.0f;
// Drag your Camera3D node here in the Inspector
[Export] public NodePath CameraPath;
private Camera3D _cam;
private float _gravity;
public override void _Ready()
{
_gravity = (float)ProjectSettings.GetSetting("physics/3d/default_gravity");
if (CameraPath != null && !CameraPath.IsEmpty)
_cam = GetNode<Camera3D>(CameraPath);
}
public override void _PhysicsProcess(double delta)
{
Vector3 v = Velocity;
if (!IsOnFloor())
v.Y -= _gravity * (float)delta;
// If you're using ui_up/ui_down etc. for WASD, keep these.
// Otherwise switch to your own actions: move_left/move_right/move_forward/move_back.
Vector2 input = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
Vector3 dir = Vector3.Zero;
if (_cam != null)
{
// In Godot, forward is -Z
Vector3 camForward = _cam.GlobalTransform.Basis.Z;
Vector3 camRight = _cam.GlobalTransform.Basis.X;
// Keep movement on the ground plane
camForward.Y = 0f;
camRight.Y = 0f;
camForward = camForward.Normalized();
camRight = camRight.Normalized();
// input.Y = forward/back (W/S), input.X = left/right (A/D)
dir = (camRight * input.X + camForward * input.Y);
if (dir.LengthSquared() > 0.000001f)
dir = dir.Normalized();
}
else
{
// Fallback: player local basis
dir = (Transform.Basis * new Vector3(input.X, 0f, input.Y)).Normalized();
}
v.X = dir.X * Speed;
v.Z = dir.Z * Speed;
if (Input.IsActionJustPressed("ui_accept") && IsOnFloor())
v.Y = JumpVelocity;
Velocity = v;
MoveAndSlide();
}
}
And this is the script attached to the CameraRig
CameraRig ← this is Node3D
- Camera3D
using Godot;
public partial class CameraRig : Node3D
{
[Export] public NodePath TargetPath;
[Export] public float FollowSpeed = 100.0f; // 높을수록 더 빠르게 따라감
[Export] public float Height = 0.0f; // 위로 띄우는 높이
[Export] public float Distance = 15.0f; // 뒤로 빼는 거리
[Export] public float YawDegrees = 45.0f; // 좌우 각도(쿼터뷰 느낌)
[Export] public float PitchDegrees = 65.0f; // 아래를 내려다보는 각도
// (옵션) 회전/줌
[Export] public bool AllowRotate = false;
[Export] public float RotateSpeedDegrees = 120.0f; // 초당 회전 속도
[Export] public bool AllowZoom = false;
[Export] public float ZoomSpeed = 10.0f;
[Export] public float MinDistance = 4.0f;
[Export] public float MaxDistance = 25.0f;
private Node3D _target;
private Camera3D _cam;
public override void _Ready()
{
_cam = GetNode<Camera3D>("Camera3D");
if (TargetPath != null && !TargetPath.IsEmpty)
_target = GetNode<Node3D>(TargetPath);
// 초기 쿼터뷰 각도
RotationDegrees = new Vector3(PitchDegrees, YawDegrees, 0f);
}
public override void _PhysicsProcess(double delta)
{
if (_target == null || _cam == null) return;
float dt = (float)delta;
// (옵션) Q/E 회전
if (AllowRotate)
{
float yawInput = 0f;
if (Input.IsActionPressed("cam_rotate_left")) yawInput -= 1f;
if (Input.IsActionPressed("cam_rotate_right")) yawInput += 1f;
YawDegrees += yawInput * RotateSpeedDegrees * dt;
}
// (옵션) 줌: 마우스휠은 InputMap에 action으로 묶는 방식 추천
if (AllowZoom)
{
float zoomInput = 0f;
if (Input.IsActionJustPressed("cam_zoom_in")) zoomInput -= 1f;
if (Input.IsActionJustPressed("cam_zoom_out")) zoomInput += 1f;
Distance = Mathf.Clamp(Distance + zoomInput * ZoomSpeed, MinDistance, MaxDistance);
}
// 리그 회전 갱신(쿼터뷰 유지)
RotationDegrees = new Vector3(PitchDegrees, YawDegrees, 0f);
// 목표 위치(플레이어 위치)로 스무딩 이동
Vector3 desiredPos = _target.GlobalPosition;
float t = 1.0f - Mathf.Exp(-FollowSpeed * dt);
GlobalPosition = GlobalPosition.Lerp(desiredPos, t);
// hard follow (no smoothing)
//GlobalPosition = _target.GlobalPosition;
// 카메라를 리그 기준으로 "위 + 뒤"에 배치
Vector3 back = -GlobalTransform.Basis.Z.Normalized();
_cam.GlobalPosition = GlobalPosition + Vector3.Up * Height + back * Distance;
//_cam.GlobalRotation = GlobalRotation;
// 항상 플레이어 바라보기
_cam.LookAt(_target.GlobalPosition, Vector3.Up);
}
}