Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Câmera em terceira pessoa com braço de mola (spring arm)

Introdução

Jogos 3D frequentemente possuem uma câmera em terceira pessoa que segue e rotaciona ao redor de algo, como o personagem do jogador ou um veículo.

No Godot, isso pode ser feito definindo uma Camera3D como filha de um nó. No entanto, se você tentar isso sem nenhuma etapa extra, notará que a câmera atravessa a geometria e esconde a cena.

É aqui que entra o nó SpringArm3D.

O que é um spring arm (braço elástico)?

Um braço de mola possui dois componentes principais que afetam o seu comportamento.

O "comprimento" (length) do braço de mola é a distância a partir da sua posição global que ele usará para verificar colisões:

../../_images/spring_arm_position_length.webp

A "forma" (shape) do braço de mola é o que ele utiliza para verificar colisões. O braço de mola vai varrer (sweep) essa forma a partir de sua origem até o limite do seu comprimento.

../../_images/spring_arm_shape.webp

O braço de mola tenta manter todos os seus filhos na extremidade do seu comprimento. Quando a forma colide com algo, os filhos são colocados no ponto de colisão ou próximo a ele:

../../_images/spring_arm_children.webp

Braço de mola com uma câmera

Quando uma câmera é colocada como filha de um braço de mola, uma pirâmide representando a câmera será usada como a forma.

Esta pirâmide representa o plano próximo (near plane) da câmera:

../../_images/spring_arm_camera_shape.webp

Nota

Se o braço de mola receber uma forma específica, então essa forma será sempre usada.

A forma da câmera só é usada se a câmera for uma filha direta do braço de mola.

Se nenhuma forma for fornecida e a câmera não for uma filha direta, o braço de mola recorrerá ao uso de um ray cast (projeção de raio), o que é impreciso para colisões de câmera e não é recomendado.

A cada quadro de processamento de física (physics process), o braço de mola realizará uma projeção de movimento (motion cast) para verificar se colidiu com alguma coisa:

../../_images/spring_arm_camera_motion_cast.webp

Quando a forma atinge algo, a câmera será colocada no ponto de colisão ou próximo a ele:

../../_images/spring_arm_camera_collision.webp

Configurando o braço de mola e a câmera

Vamos adicionar uma estrutura de câmera com braço de mola ao demo de plataforma.

Nota

Você pode baixar o demo do Platformer 3D no GitHub ou usando a Asset Library.

Em geral, para uma estrutura de câmera em terceira pessoa, você terá três nós como filhos do nó que está seguindo:

  • Node3D (the "pivot point" for the camera)

    • SpringArm3D

      • Camera3D

Abra a cena player/player.tscn. Configure estes nós como filhos do nosso jogador e dê a eles nomes únicos para que possamos encontrá-los em nosso script. Certifique-se de deletar o nó de câmera existente!

../../_images/spring_arm_editor_setup.webp

Vamos mover o ponto de pivô 2 unidades para cima no eixo Y para que ele não fique no chão:

../../_images/spring_arm_pivot_setup.webp

Dê ao braço de mola (spring arm) um comprimento de 3 para que ele seja posicionado atrás do personagem:

../../_images/spring_arm_length_setup.webp

Nota

Deixe a propriedade Shape do braço de mola como <empty> (vazia). Dessa forma, ele usará o formato de pirâmide da câmera.

Se quiser, você também pode testar outras formas — uma esfera é uma escolha comum, pois desliza suavemente ao longo das arestas.

Atualize o topo de player/player.gd para obter a câmera e os pontos de pivô pelos seus nomes únicos:

player/player.gd
# Comment out this existing camera line.
# @onready var _camera := $Target/Camera3D as Camera3D

@onready var _camera := %Camera3D as Camera3D
@onready var _camera_pivot := %CameraPivot as Node3D

Adicione uma função _unhandled_input para verificar o movimento da câmera e rotacionar o ponto de pivô de acordo:

player/player.gd
@export_range(0.0, 1.0) var mouse_sensitivity = 0.01
@export var tilt_limit = deg_to_rad(75)


func _unhandled_input(event: InputEvent) -> void:
    # Mouselook implemented using `screen_relative` for resolution-independent sensitivity.
    if event is InputEventMouseMotion:
        _camera_pivot.rotation.x -= event.screen_relative.y * mouse_sensitivity
        # Prevent the camera from rotating too far up or down.
        _camera_pivot.rotation.x = clampf(_camera_pivot.rotation.x, -tilt_limit, tilt_limit)
        _camera_pivot.rotation.y += -event.screen_relative.x * mouse_sensitivity

Ao rotacionar o ponto de pivô, o braço de mola também será rotacionado e mudará a posição onde a câmera está localizada. Execute o jogo e note que o movimento do mouse agora rotaciona a câmera ao redor do personagem. Se a câmera se mover em direção a uma parede, ela colidirá com ela.