Camera2D Second Drag Margin?

Godot Version



One of the features of Unity’s Cinemachine camera system is that it has two sets of margins: one it calls a deadzone, which acts like Godot’s Camera2D drag margins with position smoothing enabled, and a second one that causes the camera to move much faster to keep the target inside the camera limits at all times. Is it possible to implement something like this in Godot?

Try disabling smoothing when the target exits this radius around the camera

Unfortunately, that doesn’t work. First I tried it in the camera’s script:

public Rect2 GetProjectedViewportRect()
    return GetCanvasTransform().AffineInverse()*GetViewportRect();

public override void _Process(double delta)
    if (!GetProjectedViewportRect().HasPoint(GetTargetPosition()))
        PositionSmoothingEnabled = false;
        // set the drag margins to 1 so the target stays at the edge
        DragTopMargin = 1;
        DragLeftMargin = 1;
        DragBottomMargin = 1;
        DragRightMargin = 1;
        PositionSmoothingEnabled = true;
        // reset the drag margins to their original values
        DragTopMargin = 0.5f;
        DragLeftMargin = 0.5f;
        DragBottomMargin = 0.5f;
        DragRightMargin = 0.5f;

With this code, when the target moves too fast for the camera to follow and inevitably goes off-screen, the camera jumps to a position such that the node is inside the drag margin, rather than having it stay at the edge like I want (until it stops moving, and then the camera should smoothly move to a position that keeps the target inside the drag margins). However, it doesn’t do this immediately; it waits a second or so before actually jumping.

So I tried putting the code inside the camera’s target (but keeping GetProjectedViewportRect in the camera script):

public override _Process(double delta)
    Rect2 viewport = Camera.GetProjectedViewportRect();
    if (!viewport.HasPoint(Position))
        Camera.PositionSmoothingEnabled = false;
        Camera.DragTopMargin = 1;
        Camera.DragLeftMargin = 1;
        Camera.DragBottomMargin = 1;
        Camera.DragRightMargin = 1;
        Camera.PositionSmoothingEnabled = true;
        Camera.DragTopMargin = 0.5f;
        Camera.DragLeftMargin = 0.5f;
        Camera.DragBottomMargin = 0.5f;
        Camera.DragRightMargin = 0.5f;

This does the same thing as before, but there’s no delay after the target goes off-screen and the camera jumps to put it back inside the drag margins.

Why might this be happening? I took a recording of what I’m talking about, but I can’t upload it because I’m a new user. Hopefully what I wrote made sense.

Normally in this situation Id just start implementing my own solution without regards for the already existing features.

Try writing down precisely what you want the camera to do and where in form of pseudocode and then write your own implementation for the drag margins.
Only modify the camera position, let your own code do the rest.

This way you have a lot more control over the end product and can fix all the bugs you created yourself haha

I dont think the engine itself can really handle or is even designed to do specifically what you want.

Good luck bro!

I guess that is what I’m going to have to do.

Is there a way for me to be able to draw these margins in the editor? I tried drawing a rectangle using GetViewportRect(), but that just draws the editor view and not what the view will look like in-game, like you get with the Camera2D node.