The character shakes when moving

Godot Version

godot 4.3

Question

The character shakes when moving, but the camera itself remains stable despite the fact that it is attached to characterbody2d and the script itself in character body2d

can you post the script and a picture of the Node tree?

Okay. The video shows the problem, and the photo with the tree.

Code:
using Godot;
using System.Diagnostics;

public partial class Player : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 100;

private Vector2 inputDirection;
private Vector2 inputDirectionFiltered;
private Vector2 logicalPosition;
public AnimatedSprite2D character_2d;
public Label debugText;

public override void _Ready()
{
    inputDirectionFiltered = Vector2.Zero;
    logicalPosition = GlobalPosition;
    debugText = GetNode<Label>("Debug");
    character_2d = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
}

public override void _Process(double delta)
{
    if (inputDirection != Vector2.Zero)
    {
        if (Input.IsActionPressed("up"))
        {
            if (Input.IsActionPressed("right"))
            {
                character_2d.Play("forward_right");
            }
            else if (Input.IsActionPressed("left"))
            {
                character_2d.Play("forward_left");
            }
            else
            {
                character_2d.Play("forward");
            }
        }
        else if (Input.IsActionPressed("down"))
        {
            if (Input.IsActionPressed("right"))
            {
                character_2d.Play("backward_right");
            }
            else if (Input.IsActionPressed("left"))
            {
                character_2d.Play("backward_left");
            }
            else
            {
                character_2d.Play("backward");
            }
        }
        else if (Input.IsActionPressed("left"))
        {
            character_2d.Play("left");
        }
        else if (Input.IsActionPressed("right"))
        {
            character_2d.Play("right");
        }
    }

    string vectorStr = inputDirection.ToString();
    debugText.Text = vectorStr;
}

public override void _PhysicsProcess(double delta)
{
    inputDirection.X = Input.GetActionStrength("right") - Input.GetActionStrength("left");
    inputDirection.Y = (Input.GetActionStrength("down") - Input.GetActionStrength("up")) / 2;

    if (inputDirection.LengthSquared() > 0)
        inputDirection = inputDirection.Normalized();

    Velocity = inputDirection * Speed;
    MoveAndSlide();


}

}

The shaking occurs because:

1 You’re updating the character’s position directly with MoveAndSlide() in the physics process
2 The camera is following the CharacterBody2D, but it might have smoothing enabled by default

For the Solution, You need to either:

1: Disable camera smoothing to make it follow the character exactly
or
2: Apply smoothing to the character movement itself

Lmk if you need help with the code at all. I am working but I can help on my lunch break.

I use smoothing for the character, if you mean rounding up the position, I did it and the shaking went away, but it led to the wrong direction and the character to the side because I have an isometric projection, and he starts to slide down and I do not know how to deal with it. If you could help, I would be very grateful. the shaking of the character does not depend on the camera, because I even set it separately and so it was shaking.

I see the issue now. In isometric projections, simply rounding the position won’t work properly because the coordinate system is skewed.

For proper isometric movement without shaking or sliding, you need to properly. handle the isometric coordinate transformation then Apply movement smoothing that respects the isometric grid and lastly, ensure the character doesn’t drift due to floating-point precision issues.

Try something like this:

public partial class Player : CharacterBody2D
{
    [Export] public int Speed { get; set; } = 100;
    [Export] public float MovementSmoothing { get; set; } = 0.15f;
    
    // Isometric tile ratio (usually 2:1 for typical isometric)
    [Export] public float IsometricRatio { get; set; } = 0.5f;
    
    private Vector2 inputDirection;
    private Vector2 targetVelocity;
    private Vector2 currentVelocity;
    
    // Rest of your variables...

    public override void _PhysicsProcess(double delta)
    {
        // Get raw input
        inputDirection.X = Input.GetActionStrength("right") - Input.GetActionStrength("left");
        inputDirection.Y = Input.GetActionStrength("down") - Input.GetActionStrength("up");
        
        // Normalize if needed
        if (inputDirection.LengthSquared() > 0)
            inputDirection = inputDirection.Normalized();
            
        // Convert input to isometric movement
        Vector2 isoDirection = new Vector2(
            inputDirection.X - inputDirection.Y,
            (inputDirection.X + inputDirection.Y) * IsometricRatio
        );
        
        // Normalize again if needed
        if (isoDirection.LengthSquared() > 0)
            isoDirection = isoDirection.Normalized();
            
        // Set target velocity
        targetVelocity = isoDirection * Speed;
        
        // Smooth velocity changes
        currentVelocity = currentVelocity.Lerp(targetVelocity, 
            (float)(1.0 - Mathf.Exp(-MovementSmoothing / delta)));
        
        // Apply velocity
        Velocity = currentVelocity;
        MoveAndSlide();
        
        // For precise debugging
        if (debugText != null)
            debugText.Text = $"Input: {inputDirection}\nIso: {isoDirection}\nVelocity: {currentVelocity}";
    }
}

If your character is still sliding down when not moving, you might need to adjust the IsometricRatio value. The default 0.5 works for a typical 2:1 isometric projection, but you may need to experiment to find the right value for your game.

You might also want to add:

// Stop completely when no input is detected
if (inputDirection.LengthSquared() < 0.01f)
{
    currentVelocity = Vector2.Zero;
    targetVelocity = Vector2.Zero;
}

This will ensure the character stops completely when you release all movement keys, preventing any subtle drifting.

Im glad you are using C# cause I’m way more familiar with it then Gdscript but im answering questions here to help with my Gdscript skills lol.

1 Like

Thank you so much, I’ve been struggling with this for two days)) Just why did the character become very blurry when he walks along an isometric grid, that is, when I go up, everything is OK, but if I go sideways, it is blurred and a barely noticeable tremor is visible

1 Like

The video is a bit laggy, but, you see, I tried less smoothing and other methods, but it didn’t help.

I actually just recently talked about this in another topic, But cant find it for some reason.

The blurriness during isometric diagonal movement is a common issue in 2D games, especially with pixel art. This happens because of sub-pixel positioning and how sprite rendering works in game engines. Let me explain what’s happening and provide solutions.

Sub-pixel positioning is happening when moving diagonally in isometric space, your character often sits at fractional pixel coordinates (like 10.5, 15.3), causing the renderer to blend pixels.

The Interpolation happening. By default, Godot uses interpolation to smooth textures, which looks nice for static images but causes blurring during movement.

Physics/rendering mismatch, Physics updates and rendering can get slightly out of sync, causing the subtle tremor.

Some solutions that might work for you are the following.

1, Adjust the texture import settings

Select your character sprite texture in the FileSystem panel. In the Import tab, set:

Filter: Nearest (not Linear)

Mipmaps: Disabled

2, Pixel snapping for isometric movement

Try adding something like this to your code:

if (Engine.GetFramesDrawn() % 2 == 0)
{
    float snapFactor = 1.0f;
    Vector2 pixelSnapped = new Vector2(
        Mathf.Round(GlobalPosition.X * snapFactor) / snapFactor,
        Mathf.Round(GlobalPosition.Y * snapFactor) / snapFactor
    );
    GlobalPosition = pixelSnapped;
}

This approach preserves isometric alignment while reducing blur.

Lastly, Try disableing Interpolation on the camera. If you’re using a Camera2D node.

Select your Camera2D node

Enable “Process Mode: Physics” (makes camera update in sync with physics)

Disable “Position Smoothing”

Lastly, Which it looks like you have already done but just make sure.

In Project Settings,
Go to Rendering → Textures

Set “Default Texture Filter” to “Nearest”

Disable “Use Gpu Pixel Snap”

Woof, Hopefully one of these helps. Lots of reading docs for this one lol. Also start from the top down for the simplest to the stuff it might be.

3 Likes

Ohhh, the GPU pixel snap-off is the solution and your code. Thank you very much. Thank you for your time spent.

1 Like

I returned to the project, and now I see that without pixel snap, my tiles are shaking and artifacts have appeared between the tiles, so unfortunately the problem has not been solved yet, despite the fact that I have been fiddling with it for about 3 days, reread all the documentation but did not find a normal explanation, surprisingly, a lot of years have passed, graphics In 3D, it has reached almost the very reality, and in 2D graphics there are still such fundamental problems that have not yet been solved.