Pular para o conteúdo principal
dias · 10 a 12 agoengine · Godot 4.6.3 · Joltsample-âncora · Tank Controllerfonte · headers do Joltescopo · medir o limite
Execução · pontos 1 e 2 da reunião de 10/08

O tanque do Jolt e o teto do Godot.

A quinzena anterior fechou o arco conceitual do multicorpo no papel. Esta entrada é a parte empírica: rodei um sample real do Jolt, abri os headers em C++ pra descobrir de que peças ele é feito, e depois tentei remontar a mesma ideia no editor do Godot com nós Joint3D. O resultado é o comparativo formal Jolt × Godot — o entregável-âncora da semana — e a confirmação, na prática, de onde o caminho pelo nó pronto termina.

Em resumo: o Jolt tem uma peça chamada VehicleConstraint que resolve suspensão, contato e atrito de roda dentro do solver. O Godot tem um nó chamado VehicleBody3D que não é essa peça — é uma reimplementação própria, com nome parecido. E as juntas primitivas que sobram (SliderJoint3D) perdem a mola quando rodam sobre Jolt. Ou seja: pela via dos nós prontos, não dá.
Sample-âncora
Tank Controller Demo (JoltPhysics.js)
Método
Fonte primária: headers e issues
Achado central
VehicleBody3D ≠ VehicleConstraint
Regra de ouro
Junta conecta irmãos, nunca pai-filho
00

Os três dias, etapa por etapa

O plano da semana está no roadmap 10 ago – 7 set · Do sample rodando à ponte em C++. Ele separa a semana em duas faixas: a Faixa A (pontos 1 e 2 — provar até onde o Godot vai) de segunda a quarta, e a Faixa B (pontos 3 e 4 — a ponte C++) de quinta em diante. Esta entrada documenta a Faixa A inteira; a Faixa B segue em aberto.

dia 1seg · 10 ago

Rodar o sample do Jolt

Demo web do JoltPhysics.js, categoria Constraints e o Tank Controller dirigido na mão. Bloco 01.

dia 2ter · 11 ago

Comparativo formal Jolt × Godot

Anatomia do tanque lida nos headers, a distinção VehicleBody3D × VehicleConstraint e a tabela consolidada. Blocos 02 a 05.

dia 3qua · 12 ago

Replicar no Godot com Joint3D

Chassi + suspensão por SliderJoint3D, dois achados duros e o teste que bate seco. Bloco 06.

em abertoa partir de 13 ago

Faixa B · a ponte C++

Ponto 3: ler a doc do GDExtension (conceito, não construir extensão de produção). Ponto 4: espelhar o GDChrono do professor pro Jolt. Nada disso entrou nestes três dias.

Nota de método. Tudo aqui foi verificado em fonte primária — código-fonte do Jolt e issues oficiais do Godot —, não em documentação secundária ou tutorial. Quando a conclusão depende de uma evidência específica, o link está no fim da página.
01

Dia 1 · o tanque rodando

10 ago

O caminho mais curto pra ver o Jolt de verdade não é compilar os samples nativos: é a build WebAssembly (JoltPhysics.js), que roda no navegador sem nenhum setup. Passei pela categoria Constraints — as juntas “puras”, o vocabulário primitivo do motor — e escolhi como sample-âncora da semana o Tank Controller Demo: um tanque de esteiras acionado por VehicleConstraint + TrackedVehicleController. Dirigi na mão pra ver o comportamento.

O tanque gira em torno do próprio eixo, com uma física visivelmente mais estável que a do meu protótipo raycast. Saí do dia com duas dúvidas — e as duas viraram achado.
dúvida 1 · esclarecida

Por que ele gira no próprio eixo?

É direção diferencial (skid-steering): cada esteira recebe uma velocidade diferente — uma pra frente, a outra pra trás ou mais devagar — e o torque resultante dos dois lados faz o corpo pivotar. Não tem nada de mágico nem hardcoded: é distribuição de forças normal, com um controlador específico por trás decidindo a velocidade de cada lado.

dúvida 2 · esclarecida

Por que a física parece tão mais estável?

O solver do Jolt resolve todas as constraints e contatos simultaneamente e de forma implícita, a cada passo. Meu ground_contact.gd aplica força explícita por raycast, quadro a quadro. Foi essa diferença de arquitetura — não a matemática em si — que causou o bug de ejeção que resolvi com o clamp do círculo de atrito.

vista de cima · skid-steeringchassiesteira E · +vesteira D · −vtorque de guinadainput L/RTrackedVehicleController
Nenhuma roda gira pra virar. A direção sai da diferença de velocidade entre os dois lados — é isso que o VehicleWheel3D.steering do Godot, que só cobre esquema Ackermann, não sabe fazer.
Anotação-chave do dia. “Tanque usa VehicleConstraint com direção diferencial — Godot não expõe isso.” Foi essa frase que virou a pergunta do dia 2.
02

Dia 2 · de que peças o tanque é feito

11 ago

Pra montar um comparativo que sustente decisão arquitetural, não dá pra confiar em descrição de tutorial. Clonei o jrouwe/JoltPhysics e fui ler os headers direto, na branch master, dentro de Jolt/Physics/Vehicle/. Cada linha da tabela abaixo saiu de um arquivo real.

Jolt/Physics/Vehicle/ · os headers lidos
VehicleConstraint.h        // a constraint composta — o container de tudo
Wheel.h                    // roda: raycast/shape-cast, suspensão, atrito
TrackedVehicleController.h // o controlador do tanque: motor + transmissão
VehicleTrack.h             // uma esteira: razão própria + multiplicador E/D
VehicleDifferential.h      // divisão de torque (usado no controlador de carro)
PeçaO que faz (confirmado em código)
VehicleConstraintConstraint composta — containeriza tudo abaixo e entrega o conjunto pronto pro solver.
Wheel · contatoRaycast ou shape-cast por roda. Mesmo princípio do meu RayCast3D — só que embutido na constraint, não solto num script.
Wheel · suspensãoMola por roda, com curso dedicado (mSuspensionMinLength / mSuspensionMaxLength).
TrackedVehicleControllerDono do motor (VehicleEngine, curva de torque × RPM) e da transmissão (VehicleTransmission) — únicos, compartilhados pelas duas esteiras.
VehicleTrackUma por lado. Tem razão de engrenagem própria (mDifferentialRatio) mais um multiplicador (mLeftRatio / mRightRatio) — é esse multiplicador que produz o skid-steer.
Atrito por rodaCoeficientes fixos (mLongitudinalFriction, mLateralFriction) — mais simples que o modelo de carro, que usa curva de slip.
Correção que registrei. Minha primeira leitura foi “cada esteira tem seu próprio motor”. Errado. São um motor e uma transmissão únicos; o que diferencia esquerda de direita é só o multiplicador de razão de cada VehicleTrack. A diferença importa: o torque disponível é um recurso compartilhado, não dois independentes.

Este bloco levanta de que peças o veículo do Jolt é feito. Como elas operam por dentro — o raycast que encontra o chão, o ciclo de um passo de física e as equações de cada roda — está em Um corpo só, quatro bengalas.

03

A dúvida grande: VehicleBody3D é o VehicleConstraint?

11 ago

O Godot 4.6 passou a usar o Jolt como backend padrão de física. A pergunta óbvia, então: quando eu ponho um VehicleBody3D na cena rodando sobre Jolt, estou usando o VehicleConstraint real por baixo? A resposta muda tudo — se fosse sim, a semana inteira seria desnecessária.

Não. São duas implementações completamente separadas, com nome parecido.
caminho do nó do GodotVehicleBody3Dnó da cenaPhysicsServer3DGodotPhysicslógica própriabackend Joltlógica própriao que existe dentro do Jolt (C++)VehicleConstraintAPI C++ · nunca expostaWheel[]Controllersolver de constraintstudo resolvido junto, por passoessa ligação não existe
Nome parecido, caminho diferente. O VehicleBody3D é uma abstração do próprio Godot, no nível do PhysicsServer3D — cada backend implementa a lógica de veículo por conta própria. O VehicleConstraint do Jolt fica do outro lado da linha, sem porta de entrada pelo editor.

É anterior ao Jolt no engine

O VehicleBody3D existe desde antes de o Jolt ser opção no Godot, baseado no sistema clássico de veículo por raycast. Ele vive no nível do PhysicsServer3D, e cada backend de física precisa implementar aquela lógica por conta própria.

O comportamento diverge entre backends

O guia de migração do Godot 4.6 confirma: suspensão, atrito de pneu e trem de força produzem resultados diferentes no GodotPhysics e no Jolt. Se o nó chamasse a mesma peça C++ por baixo, não haveria divergência a documentar.Divergência entre backends é a assinatura de reimplementação, não de reaproveitamento.

A prova mais forte: alguém está pedindo

Existe uma proposal aberta e recente nos godot-proposals pedindo exatamente a exposição das vehicle constraints reais do Jolt — o que só faz sentido se elas ainda não estiverem expostas. Há também uma proposal mais geral sobre as constraints do Jolt indisponíveis no Godot.

A analogia que fixou o conceito. O VehicleBody3D é um controle remoto universal: os botões (acelerar, frear, virar) são sempre os mesmos, mas cada “TV” — cada motor de física — reage do seu próprio jeito por trás. O VehicleConstraint é o controle de fábrica, feito sob medida pras peças internas do Jolt.
Implicação prática pro rover. O VehicleWheel3D.steering só cobre esquema Ackermann — roda que gira, como num carro. Não achei suporte nativo a direção diferencial / skid-steer no VehicleBody3D. Pra ter isso de verdade, o caminho é GDExtension, não o nó pronto.
04

O que é, exatamente, um “Controller”

11 ago

O VehicleConstraint resolve só a parte genérica de um veículo: contato de roda, suspensão e atrito. Quem traduz o input do jogador em força nas rodas é uma camada plugável em cima dele — o Controller. Essa separação é a peça de arquitetura que mais me interessa a longo prazo.

Motor

A curva de torque × RPM — quanta força o conjunto tem disponível em cada regime.

Câmbio

As relações de marcha: como o torque do motor é convertido antes de chegar às rodas.

Diferencial

Como o torque se divide entre as rodas — a peça que existe no controlador de carro e não no de tanque.

carro

WheeledVehicleController

Diferencial de verdade mais direção por ângulo de roda (Ackermann). É o modelo que o VehicleBody3D do Godot tenta cobrir.

tanque

TrackedVehicleController

Sem diferencial e sem roda que gira: a velocidade de cada esteira vem direto do input L/R. É o modelo que o rover provavelmente vai usar.

Por que isso importa pro projeto. Essa separação — contato genérico de um lado, lógica de acionamento do outro — é o modelo de referência pro Mês 4 do cronograma (motores/atuadores e modelos de roda). O Jolt já resolveu essa arquitetura; não preciso inventá-la, preciso entendê-la.
05

O comparativo formal · entregável-âncora

11 ago

A tabela que o roadmap da semana pede: feature a feature, o que o Jolt tem nativamente e o que o Godot 4.6 expõe. Não é opinião sobre qual caminho seguir — é o levantamento que fundamenta a decisão.

FeatureJoltGodot expõe?Observação
VehicleConstraint · a constraint compostasimnãoSó existe como API C++.
VehicleBody3D · o nó do Godotsim, mas…Reimplementação própria do Godot; não usa o VehicleConstraint por baixo e diverge no comportamento mesmo rodando sobre Jolt.
Raycast de contato por rodasimparcialNo Jolt vem embutido na constraint. No Godot o RayCast3D genérico existe, mas solto — não integrado a um sistema de veículo.
Suspensão spring-damper por rodasimparcialNo Jolt, com curso mín/máx dedicado por roda. No Godot, via VehicleWheel3D — mas com a física própria do backend.
TrackedVehicleController · motor + câmbio compartilhadossimnão
VehicleTrack · razão + multiplicador E/D → skid-steersimnãoVehicleWheel3D.steering só cobre Ackermann.
Atrito da roda · círculo de atrito embutidosimnãoReimplementei isso na mão no protótipo raycast — foi de onde veio o bug da ejeção.
06

Dia 3 · replicar no Godot com Joint3D

12 ago

O ponto 2 do roadmap pede pra tentar reconstruir o cenário do sample usando só nós Joint3D — não pra entregar um veículo, mas pra medir onde a coisa bate no limite. O ajuste de escopo veio antes de abrir o editor.

Ajuste de escopo. O VehicleConstraint não tem nenhum equivalente em Joint3D — é uma peça composta própria. Replicar o Tank literalmente exigiria simular uma corrente de corpos rígidos (as esteiras), o que é projeto próprio, não tarefa de um dia. Decisão: em vez do tanque, testar o limite com o veículo de rodas físico mais simples possível, reaproveitando a arquitetura já projetada na quinzena anterior — 1 chassi + 4 SliderJoint3D (suspensão) + 4 HingeJoint3D (rodas). Montei só o chassi e uma roda (frente-esquerda): o suficiente pra encontrar o teto.

Achado 1 · SliderJoint3D no Jolt não tem mola de verdade

A issue rastreadora do godot-jolt lista, parâmetro a parâmetro, o que o backend Jolt suporta do SliderJoint3D. O status dela é “Done — as much as it can be”: não é um item pendente que um dia será feito, é o teto do que dá pra mapear.

Parâmetro do SliderJoint3DFunciona no Jolt?
Limite superior / inferior (curso)sim
Softness / Restitution / Damping do limitenão · incompatível com a SliderConstraint
Softness / Restitution / Damping do movimento livrenão
Limites e motor angularesnão · a própria issue recomenda Generic6DOFJoint3D
Traduzindo. No backend Jolt, o SliderJoint3D dá apenas um batente rígido. Todos os parâmetros que produziriam efeito de mola são ignorados silenciosamente — sem erro, sem aviso no editor. O inspetor mostra campos que não fazem nada.

Achado 2 · RigidBody3D não pode ser filho de outro RigidBody3D em movimento

sintoma

O conjunto tombava sozinho em queda livre

Montei RodaSuporte_FE como filho do Chassi — os dois RigidBody3D. O conjunto tombava sozinho durante a queda, mesmo sem tocar o chão, e sempre pro lado onde estava o corpo aninhado.

causa · e a correção

Aninhamento de corpos rígidos não é confiável

Isolei tirando o chão da equação — só queda livre —, o que confirmou que o problema era estrutural, não de contato. A causa está registrada na issue godotengine/godot#120067: um RigidBody3D não segue de forma confiável um RigidBody3D pai em movimento. É comportamento de longa data do engine, não particularidade do meu setup. Correção: corpos ligados por junta devem ser irmãos na árvore — a junta já faz a ligação física, a hierarquia de nós não precisa (e não deve) refleti-la.

◉ MundoTesteNode3D · raiz da cena
├─ ChaoStaticBody3D · o piso
├─ ChassiRigidBody3D · o corpo principal
├─ RodaSuporte_FERigidBody3D · irmão do chassi, não filho
└─ Susp_FESliderJoint3D · nodes A e B apontando pros dois irmãos
A regra: a junta é quem conecta. Aninhar corpo rígido dentro de corpo rígido não “prende” nada — só quebra.

O teste final

Com a estrutura corrigida (chassi e suporte de roda como irmãos, ligados pelo Susp_FE) e o chão de volta, rodei a cena. O contato aconteceu — e o conjunto bateu seco, sem nenhum efeito de suspensão visível.

o que eu esperava · molao que aconteceu · batentecurso comprime, oscila, assentacai, encosta, para — curso zero de amortecimento
Confirmação empírica do Achado 1. O comportamento observado é exatamente o previsto pela issue godot-jolt#109 — o limite existe, a mola não.
Anotação-chave do dia. “Tentativa de suspensão via SliderJoint3D no Godot/Jolt: bate seco, sem mola. Confirma empiricamente a limitação documentada no godot-jolt#109 — a VehicleConstraint nativa do Jolt resolve isso internamente; a via Joint3D não tem substituto.” Isso fecha o ponto 2 da reunião: medir até onde o Godot chega, e onde bate no limite.
07

Síntese dos três dias

Três achados sustentam a decisão arquitetural, todos verificados em fonte primária — código-fonte ou issue oficial, não documentação secundária.

Lacuna de API

O VehicleConstraint do Jolt não tem equivalente em Joint3D, e o VehicleBody3D do Godot não é uma exposição dele — é uma reimplementação própria e paralela.

Lacuna de suporte no backend Jolt

Mesmo as juntas primitivas que existem perdem funcionalidade quando rodam sobre Jolt: o SliderJoint3D fica sem mola. Documentado, e não vai mudar.

Gotcha de implementação

RigidBody3D aninhado em outro RigidBody3D móvel é estruturalmente não confiável no Godot.Regra de ouro pra qualquer rig multicorpos daqui pra frente: juntas conectam irmãos, nunca pai-filho.

em aberto

Esquema de direção do rover

Skid-steer como o tanque, ou Ackermann como o carro? É decisão do professor e ainda não foi definida — e ela muda qual dos dois controllers do Jolt vira o modelo de referência.

opcional

As outras três rodas

Montar o resto do veículo físico é opcional a partir daqui: o achado central já está confirmado e documentado. Só faz sentido se eu precisar do rig pra outra coisa.

Próximos passos da semana · Faixa B. Ponto 3: ler a doc do GDExtension — o conceito, não construir uma extensão de produção. Ponto 4: espelhar o GDChrono do professor pro Jolt. É o caminho que, se aberto, contorna os três achados acima.

Contexto anterior: o arco conceitual está em Constraints, juntas e o Jolt por dentro, e o ponto de partida — por que o VehicleBody3D não é um multicorpo de verdade — está na nota do sandbox no Godot.

Fontes

dia 1 · o sample do Jolt
JoltPhysics.js — demos webbuild WebAssembly · roda sem nenhum setup↗ demoTank Controller Demoo sample-âncora da semana↗ demoWheeled Vehicle Controller Demoo contraponto de carro, com Ackermann↗ demoConstraints Demoas juntas “puras” — o vocabulário primitivo↗ demojrouwe/JoltPhysicsrepositório clonado pra verificação em código↗ githubDocs/Samples.mddoc oficial dos samples nativos↗ github
dia 2 · headers verificados (branch master)
VehicleConstraint.ha constraint composta↗ headerWheel.hcontato, suspensão e atrito por roda↗ headerTrackedVehicleController.hmotor e transmissão únicos, compartilhados↗ headerVehicleTrack.hrazão por esteira · onde nasce o skid-steer↗ headerVehicleDifferential.hdivisão de torque · usado no controlador de carro↗ headerJolt/Physics/Constraintslista completa das constraints primitivas↗ pasta
dia 2 · evidência de que VehicleBody3D ≠ VehicleConstraint
Godot 4.6 Jolt Physics — Migration GuideJolt vira padrão · a divergência de comportamento do VehicleBody3D↗ blogAdd Jolt Vehicle constraintsproposal aberta pedindo as vehicle constraints reais do Jolt↗ proposalsConstraints do Jolt não disponíveis no Godotproposal relacionada, mais geral↗ proposalsVehicleBody3Ddoc oficial do nó · a API que o Godot expõe↗ godot docs
dia 3 · os dois achados
SliderJoint3D não suporta mola no Joltgodot-jolt #109 · issue rastreadora, status “Done — as much as it can be”↗ githubRigidBody3D não confiável como filho de outro RigidBody3D em movimentogodot #120067 · a causa do tombamento em queda livre↗ github