Materiais do vídeo
Rope Simulation in Uncharted 4 and The Last of Us 2Palestra · GDC Vault · inglês↗Position Based Dynamics (artigo original)Artigo científico · Müller e outros · inglês↗Ten Minute PhysicsTutoriais em vídeo · grátis · inglês↗Advanced Character Physics (Verlet em jogos)Artigo · Game Developer · inglês↗Corda que enrola nas quinas (gancho 2D)Tutorial · Kodeco · inglês↗UnityVerletRopeRepositório · GitHub · C# para Unity↗Verlet Rope 4Repositório · GitHub · C# para Godot↗Obi RopeAsset · Unity · inglês↗Cable ComponentDocumentação · Epic Games · inglês↗Como fazer a corda de The Last of Us Part II no seu jogo
A palestra da Naughty Dog sobre a corda de 14 metros e como fazer uma no seu jogo: Position Based Dynamics explicado com analogias, código em JavaScript que roda no navegador, a corda esticada que dobra nas quinas e projetos prontos em Unity, Godot e Unreal.
Você veio do vídeo da corda de The Last of Us Part II e aqui está a versão completa. Primeiro, a palestra da Naughty Dog e o que ela cobre. Depois, como fazer uma corda dessas no seu jogo: a física sem matemática pesada, um código curto que roda no navegador e a ideia da corda esticada que dobra nas quinas. No fim tem projetos prontos em Unity, Godot e Unreal, o bastidor, vídeos e um glossário.
Resumo pra quem tem pressa
A corda do jogo funciona em dois modos. Quando está frouxa, ela é uma fileira de pontinhos que a física move a cada quadro. Quando estica, esse jeito começa a falhar, e o jogo passa a desenhar a corda como linhas retas que só dobram nas quinas dos objetos.
| Parte | O que faz | Onde aprender |
|---|---|---|
| A palestra | Conta a história da corda do Uncharted 4 ao TLOU2 e explica os dois modos | GDC Vault |
| Corda frouxa (PBD) | Gravidade empurra cada ponto, depois o jogo corrige as posições para manter a distância entre vizinhos e tirar quem entrou na parede | Artigo original de PBD e o Ten Minute Physics |
| Verlet | O mesmo espírito, com a velocidade guardada na diferença entre a posição atual e a anterior | Advanced Character Physics |
| Corda esticada | Uma linha que vai reta e só dobra onde encosta numa quina | Tutorial de gancho com pontos de dobra |
| Pronto pra usar | Corda já feita para testar no seu motor | Obi Rope, Verlet Rope 4, Cable Component |
A palestra da Naughty Dog
O nome é "Rope Simulation in 'Uncharted 4' and 'The Last of Us 2'". Quem apresenta é Jaroslav Sinecky, da Naughty Dog, na GDC de 2021, na trilha de programação. A página fica no GDC Vault.
O resumo oficial conta três coisas:
- Uncharted 4: a equipe precisou criar uma tecnologia nova de corda para o gancho do Drake e o guincho do jipe. A corda tinha que dobrar e enrolar nos objetos do cenário.
- The Last of Us Part II: a mesma tecnologia foi além para os puzzles de corda. O jogador joga 14 metros de corda no cenário e pega de volta em qualquer ponto.
- O conteúdo técnico: a palestra passa pela história do desenvolvimento e pelos maiores problemas no caminho. Depois explica a simulação de corpo mole (a corda frouxa) e a técnica usada para resolver a corda esticada enrolando nos objetos.
Como assistir: a palestra completa em vídeo é para assinantes do GDC Vault. Se o player não abrir para você, esta página cobre as ideias principais. Nos slides, um dos títulos é "Rope PBD", na parte de colisão, e outro é "Taut rope simulation" (simulação da corda esticada). Esses dois nomes guiam as duas metades desta página.
Por que uma corda é tão difícil
Parece só uma linha. O problema é tudo que o jogador faz com ela.
- Ela é comprida: 14 metros, com muita coisa no caminho.
- Ela cai, dobra, enrola em poste e desliza pelas superfícies. Cada pedacinho precisa respeitar o cenário.
- Você pega em qualquer ponto. Não existe uma "ponta certa" para segurar.
- Tudo em tempo real, em poucos milissegundos por quadro, junto com o resto do jogo.
Uma animação pronta não resolve, porque quem decide onde a corda vai parar é o jogador. A corda precisa ser simulada, e na parte frouxa a Naughty Dog usou PBD.
Corda frouxa: Position Based Dynamics (PBD)
A ideia em uma frase
Em vez de calcular forças e esperar que elas levem os pontos ao lugar certo, você move os pontos e depois corrige as posições até as regras serem cumpridas.
Pensa num colar de contas. Você solta o colar, a gravidade puxa cada conta para baixo, e o fio impede que uma conta se afaste demais da vizinha. O PBD faz exatamente isso, em dois tempos: primeiro deixa cada conta cair livre, depois "puxa o fio" para colocar todo mundo de volta na distância certa.
O artigo que deu nome a isso é "Position Based Dynamics", de Matthias Müller, Bruno Heidelberger, Marcus Hennix e John Ratcliff, na época da AGEIA. Ele foi apresentado em 2006 no workshop VRIPHYS, da Eurographics, e saiu em versão de revista em 2007 no Journal of Visual Communication and Image Representation. O resumo diz o que mudou: em vez de passar por forças e velocidades, o método trabalha direto nas posições, o que dá mais controle, evita que a simulação "passe do ponto" e deixa a colisão simples, porque basta empurrar o ponto para um lugar válido.
O laço de cada quadro
O passo de tempo do artigo, em português claro:
- Aplique as forças de fora. A gravidade muda a velocidade de cada ponto. Aqui também entra um pouco de amortecimento.
- Preveja a posição nova. Cada ponto anda na direção da velocidade dele. Essa é só uma previsão.
- Descubra as colisões. Para cada ponto que vai entrar num objeto, crie uma regra: "fique do lado de fora".
- Corrija várias vezes. Passe por todas as regras (distância entre vizinhos e colisões) e ajuste as posições previstas. Repita algumas vezes.
- Atualize a velocidade. A velocidade nova é o quanto o ponto andou, dividido pelo tempo. A posição prevista vira a posição oficial.
O truque está no passo 5. Como a velocidade sai da posição corrigida, ela já nasce coerente com as regras. Isso deixa a simulação bem estável.
A restrição de distância
A regra principal de uma corda é: cada ponto fica a uma distância fixa do vizinho.
Se dois pontos estão mais longe do que deviam, o jogo puxa os dois um na direção do outro. Se estão perto demais, empurra. Quanto cada um anda depende do peso: o ponto pesado anda pouco e o leve anda muito. Um ponto preso (na mão do personagem, por exemplo) tem "peso infinito" e não anda nada.
No artigo, o peso entra como massa inversa (w = 1 / massa). Um ponto preso tem w = 0. A correção de cada ponto é a fração w_dele / (w1 + w2) do erro, na direção da linha que liga os dois. Com dois pontos de mesmo peso, cada um anda metade do erro. É só isso que o código mais abaixo faz.
Iterações: por que repetir deixa a corda mais dura
Corrigir um par de pontos desarruma o par do lado. Por isso o jogo passa pela corda inteira várias vezes por quadro. Cada passada é uma iteração.
O artigo explica a consequência: quanto mais iterações, mais dura a corda fica. Com poucas, ela estica como elástico. Com muitas, ela se comporta como corda de verdade, mas custa mais processamento.
Pensa numa fila de pessoas de mãos dadas. A da ponta dá um passo, a vizinha acompanha, depois a próxima. Com pouco tempo, a correção não chega ao fim da fila. Numa corda com dezenas de pontos, é isso que acontece.
Dica: em vez de aumentar só as iterações, divida o quadro em passos menores (substeps). O artigo "Small Steps in Physics Simulation" (Macklin e outros, 2019) mostra que vários passos pequenos com uma iteração cada resolvem melhor do que um passo grande com muitas iterações. O projeto de Unity que aparece mais abaixo faz isso.
Colisão: empurra pra fora
Se um ponto entrou no poste, você coloca o ponto de volta na superfície. O artigo faz isso testando o caminho entre a posição antiga e a prevista: se esse trecho entra num objeto, nasce uma regra que mantém o ponto do lado de fora. Se o ponto já está todo dentro, ele é levado para o ponto mais perto da superfície.
Como a velocidade é calculada depois, a corda perde a velocidade que tinha "para dentro" da parede sem você escrever nenhuma conta de quique.
E o Verlet?
Você vai ver muito tutorial chamado "verlet rope". É a mesma família de ideias, um pouco mais antiga. Thomas Jakobsen, chefe de pesquisa da IO Interactive, descreveu no artigo Advanced Character Physics, publicado no Gamasutra em 2003, o sistema usado em Hitman: Codename 47 para pano, plantas e corpos caindo.
A diferença está em onde mora a velocidade:
- Verlet: cada ponto guarda a posição atual e a anterior. A velocidade é a diferença entre as duas. Não existe variável de velocidade.
- PBD: cada ponto guarda posição e velocidade, e a velocidade é recalculada no fim do passo.
O resto é igual: prever, corrigir a distância entre vizinhos várias vezes e empurrar para fora de quem colidiu. O próprio artigo de PBD diz que a projeção de distância de Jakobsen é um caso especial do método deles. Jakobsen deixa uma frase que resume a filosofia dos jogos: o que importa é parecer convincente, e o programador pode trapacear o quanto quiser se o jogador continua imerso.
Mão na massa: uma corda PBD em JavaScript
O código abaixo é uma corda em 2D com 30 pontos, presa numa ponta, caindo sobre um poste redondo. Ele usa o estilo Verlet (posição atual e anterior) para a inércia e o PBD para as correções. O código foi testado: depois de 5 segundos simulados, a corda fica apoiada no poste, nenhum ponto fica dentro dele e a maior diferença de distância entre vizinhos fica abaixo de 0,3 pixel.
// Corda PBD simples em 2D (y cresce para baixo, como no canvas)
const N = 30; // quantos pontinhos
const SEG = 10; // distância entre vizinhos (pixels)
const GRAVIDADE = 980; // pixels por segundo ao quadrado
const ITERACOES = 20; // quantas vezes corrigir por quadro
const pontos = [];
for (let i = 0; i < N; i++) {
pontos.push({ x: 200 + i * SEG, y: 100, px: 200 + i * SEG, py: 100, w: 1 });
}
pontos[0].w = 0; // w = 1/massa. Zero = preso na mão (não se mexe)
const poste = { x: 300, y: 260, r: 40 }; // obstáculo redondo
function passo(dt) {
// 1) prever: inércia + gravidade
for (const p of pontos) {
if (p.w === 0) continue;
const vx = (p.x - p.px) * 0.99; // 0.99 = amortecimento leve
const vy = (p.y - p.py) * 0.99;
p.px = p.x; p.py = p.y;
p.x += vx;
p.y += vy + GRAVIDADE * dt * dt;
}
// 2) corrigir: várias passadas pelas restrições
for (let k = 0; k < ITERACOES; k++) {
// 2a) distância entre vizinhos
for (let i = 0; i < N - 1; i++) {
const a = pontos[i], b = pontos[i + 1];
const dx = b.x - a.x, dy = b.y - a.y;
const dist = Math.hypot(dx, dy);
const somaW = a.w + b.w;
if (dist === 0 || somaW === 0) continue;
const erro = (dist - SEG) / dist / somaW;
a.x += dx * erro * a.w; a.y += dy * erro * a.w;
b.x -= dx * erro * b.w; b.y -= dy * erro * b.w;
}
// 2b) colisão: quem entrou no poste volta para a borda
for (const p of pontos) {
if (p.w === 0) continue;
const dx = p.x - poste.x, dy = p.y - poste.y;
const dist = Math.hypot(dx, dy);
if (dist < poste.r && dist > 0) {
p.x = poste.x + (dx / dist) * poste.r;
p.y = poste.y + (dy / dist) * poste.r;
}
}
}
}
Para ver na tela, crie um arquivo HTML com <canvas width="600" height="500"></canvas>, cole o código acima num <script> e acrescente o desenho. A ponta presa segue o mouse:
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.addEventListener('mousemove', (e) => {
pontos[0].x = e.offsetX;
pontos[0].y = e.offsetY;
});
function quadro() {
passo(1 / 60);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(poste.x, poste.y, poste.r, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.moveTo(pontos[0].x, pontos[0].y);
for (const p of pontos) ctx.lineTo(p.x, p.y);
ctx.stroke();
requestAnimationFrame(quadro);
}
quadro();
O que mexer para sentir a física:
ITERACOESem 2: a corda vira elástico. Em 50, fica bem mais firme.0.99em 1: sem amortecimento, ela balança por muito mais tempo.SEGmenor eNmaior: a corda fica mais lisa e mais cara de calcular.
Pegar em qualquer ponto
No PBD, pegar a corda em qualquer lugar é quase de graça. Para segurar o ponto 17, você faz pontos[17].w = 0 e coloca esse ponto na mão do personagem a cada quadro. A restrição de distância cuida do resto: os dois lados da corda passam a pender da mão. Para soltar, volte o w para 1. Essa é a forma padrão de prender pontos no PBD, não um detalhe confirmado da implementação da Naughty Dog.
O mesmo laço em C#, num projeto real
O repositório UnityVerletRope faz a versão 3D disso em Unity, em C#. O laço tem a mesma estrutura: substeps, Verlet, várias correções de distância e colisão com a cena usando esferas da física da Unity.

Corda esticada: o caminho pelas quinas
Por que o PBD sofre quando a corda estica
Com a corda frouxa, as regras quase não brigam. Quando o personagem estica a corda em volta de um poste, elas puxam em direções opostas: a distância entre vizinhos quer encurtar, a colisão empurra para fora e a mão continua puxando. Três coisas pioram o quadro:
- A correção demora a percorrer a corda. Como vimos nas iterações, a "notícia" de que a ponta foi puxada leva várias passadas para chegar ao outro lado. Em 14 metros de corda, isso aparece.
- Uma quina é um ponto só. A corda é feita de pontinhos separados. Entre dois pontinhos, o segmento reto pode cortar a quina, e os pontos ficam escorregando de um lado para o outro da aresta.
- Cada quadro recomeça a briga. O resultado é o que a legenda do vídeo descreve: os pontinhos tremem e escorregam pelas quinas.
Essa explicação é leitura minha, baseada no artigo de PBD. O resumo da palestra confirma que a corda esticada enrolando nos objetos pediu uma técnica própria.
A ideia da Naughty Dog, lida no slide
Pelo desenho do slide "Taut rope simulation", a corda esticada deixa de ser uma fileira de pontinhos soltos. O jogo traça uma linha reta que só dobra nas quinas dos objetos, que é o caminho mais curto em volta do obstáculo. Quando a corda volta a ficar frouxa, a simulação PBD assume de novo.
Um aviso: isso é o que dá para ler no desenho do slide. A explicação falada da palestra não foi ouvida para esta página, então os detalhes de como a Naughty Dog detecta as quinas e troca de modo ficam na palestra.
Pensa num elástico preso num prego e esticado em volta de uma caixa. Ele vai reto até uma quina, dobra e vai reto até a próxima. Quem decide a forma dele são as quinas que ele toca.
Uma versão simples, em 2D
Uma técnica comum em tutoriais de gancho é a dos pontos de dobra (wrap points). O tutorial Make a 2D Grappling Hook Game in Unity, de Sean Duffy (Kodeco, 2017), faz assim: lança um raio do jogador até o último ponto de apoio da corda. Se o raio bate num objeto, o jogo pega a quina do objeto mais perto do ponto de batida e ela vira um novo ponto de apoio. A parte 2 ensina a desenrolar, comparando de que lado da quina o jogador está.
Em pseudocódigo:
caminho = [ancora] // pontos de dobra, da âncora até a mão
a cada quadro:
ultimo = caminho[fim]
se o raio de ultimo até a mão bate num objeto:
quina = vértice do objeto mais perto da batida
caminho.adicionar(quina) // a corda dobrou aqui
se caminho tem 2 pontos ou mais:
penultimo = caminho[fim - 1]
se a mão passou para o outro lado da última quina
e o raio de penultimo até a mão está livre:
caminho.remover_ultimo() // a corda desenrolou
comprimento_usado = soma dos trechos do caminho + trecho até a mão
desenhe linhas retas entre os pontos do caminho
Com o comprimento_usado você limita até onde o personagem vai: se chegou ao tamanho da corda, ela está esticada e segura o personagem. É bem mais simples que um jogo 3D comercial, mas mostra a ideia central: na corda esticada, o que importa são as quinas, não os pontinhos.
Dica: se você já mexeu com navegação de personagens, vai reconhecer o padrão. Achar o caminho mais curto que só dobra em quinas é o mesmo problema do "string pulling" em navmesh. O texto Simple Stupid Funnel Algorithm, de Mikko Mononen, mostra um algoritmo curto para isso. A ligação com a corda é leitura minha, não algo dito na palestra.
Juntando os dois modos
Um jeito de organizar o seu código, inspirado na divisão da palestra:
- Frouxa: simulação PBD com todos os pontos, colisão e gravidade.
- Esticada: lista de pontos de dobra, linhas retas entre eles e o comprimento total limitando o personagem.
- Troca: quando a soma dos trechos chega ao comprimento da corda, ela estica. Quando o personagem se aproxima e sobra corda, você distribui os pontinhos de novo ao longo do caminho e volta para o PBD.
As regras exatas de troca do TLOU2 não estão no resumo público. Isso é uma sugestão para o seu projeto.
Pronto pra testar no seu motor
Para ter a corda funcionando hoje e estudar depois:
| Projeto | Motor | Como funciona | Preço |
|---|---|---|---|
| Obi Rope | Unity | Partículas com restrições de distância e de dobra, na CPU e na GPU. A corda pode rasgar e mudar de tamanho (documentação) | Asset Store da Unity |
| UnityVerletRope | Unity | Verlet com substeps, iterações e colisão | Grátis, código aberto |
| Verlet Rope 4 | Godot 4.4 ou mais novo, versão .NET | Verlet em C#, com vento, gravidade e colisão | Grátis, licença MIT |
| Cable Component | Unreal Engine | Partículas ligadas por restrições de distância, integradas com Verlet | Plugin oficial da Epic |
Cable Component (Unreal)
A documentação do Cable Component descreve o modelo desta página: partículas ligadas por restrições de distância, pontas presas e as do meio caindo com a gravidade, integradas com Verlet. Duas opções importam:
- Solver Iterations: a própria documentação diz que o número de iterações controla o quanto o cabo é duro. É a mesma ideia das iterações do PBD.
- Enable Collision: faz cada partícula testar o cenário a cada substep. A documentação marca como experimental e avisa que aumenta muito o custo.
Bastidor: três meses numa corda
O jogo saiu em 19 de junho de 2020. No mesmo dia, o desenvolvedor Renji Nikaido postou um vídeo mostrando o quanto dava para enrolar e embaraçar os cabos no jogo, e o vídeo viralizou. Vários desenvolvedores elogiaram o trabalho.
Maksym Zhuravlov, animador técnico da Naughty Dog, contou o tamanho do trabalho. Segundo a Inverse (Danny Paez, 27 de junho de 2020), ele e dois colegas levaram cerca de três meses para criar o sistema de corda, e a equipe de testes (QA) testou até não poder mais antes do lançamento.
A GamePro alemã (22 de junho de 2020) completa o quadro: Kurt Margenau, codiretor do jogo, deu o crédito ao programador Jaroslav Sinecky, e o próprio Zhuravlov disse que Sinecky fez a maior parte do trabalho. Sinecky é justamente quem apresentou a palestra na GDC no ano seguinte.
Uma única mecânica levou meses de três pessoas, mais o time de testes. E ela não nasceu do zero: a base veio do gancho e do guincho do Uncharted 4.
Os erros mais comuns
- Poucas iterações numa corda comprida. Ela estica como chiclete. Aumente as iterações ou use substeps.
- Esquecer o amortecimento. Sem ele, a corda balança para sempre e parece leve demais.
- Pontos espaçados demais para o tamanho do obstáculo. A corda atravessa objetos finos e corta quinas. Ou diminua o espaço entre pontos, ou trate a colisão como uma linha entre vizinhos, não só como pontos.
- Passo de tempo variável. O artigo de PBD avisa que a rigidez depende do passo de tempo. Simule com passo fixo, mesmo que o jogo rode em taxas de quadro diferentes.
- Tentar resolver a corda esticada só com mais iterações. Uma hora o custo explode e a corda continua escorregando nas quinas. É o momento de pensar em pontos de dobra.
Vídeos
Matthias Müller, primeiro autor do artigo de PBD, simula um pêndulo triplo com restrições de distância no canal Ten Minute Physics. A mesma técnica serve para corda, cabelo e pano (em inglês):
O passo seguinte é o XPBD, versão do PBD em que a rigidez não depende do número de iterações (em inglês):
Pra ir mais fundo
A palestra e o bastidor
- Rope Simulation in 'Uncharted 4' and 'The Last of Us 2' (GDC Vault, 2021): a fonte de tudo. Leia o resumo e assista se tiver acesso.
- Inverse sobre a corda do TLOU2 (2020): os três meses e as três pessoas, contados pelo Zhuravlov.
- GamePro sobre a física da corda (2020, em alemão): quem recebeu o crédito dentro da Naughty Dog.
A teoria
- Position Based Dynamics (Müller e outros, 2006/2007): o artigo original. As seções do algoritmo e da restrição de distância são curtas e legíveis. Ficha na biblioteca da Eurographics.
- Advanced Character Physics (Thomas Jakobsen): o texto clássico do Verlet em jogos, do tempo do Hitman.
- XPBD (Macklin, Müller e Chentanez, 2016): resolve o problema da rigidez que muda com as iterações e com o passo de tempo.
- Small Steps in Physics Simulation (Macklin e outros, 2019): por que vários passos pequenos ganham de muitas iterações.
Tutoriais
- Ten Minute Physics: vídeos curtos com código em HTML e JavaScript que roda no navegador. Comece pelos tutoriais 05 e 06.
- Make a 2D Grappling Hook Game in Unity, parte 1 e parte 2 (Kodeco): os pontos de dobra na prática, enrolando e desenrolando.
- Simple Stupid Funnel Algorithm (Mikko Mononen): o caminho mais curto que dobra nas quinas, do mundo da navegação.
Glossário rápido
| Termo | Em português claro |
|---|---|
| PBD (Position Based Dynamics) | Simular movendo os pontos e depois corrigindo as posições até as regras serem cumpridas |
| Verlet | Jeito de simular em que a velocidade é a diferença entre a posição atual e a anterior |
| Restrição | Uma regra que a simulação precisa cumprir, como "fique a 10 cm do vizinho" |
| Restrição de distância | A regra que faz a corda ser corda: vizinhos sempre na mesma distância |
| Iteração | Uma passada corrigindo todas as regras. Mais passadas, corda mais dura |
| Substep | Dividir um quadro em passos menores para a simulação ficar mais precisa |
| Massa inversa | 1 dividido pela massa. Zero quer dizer ponto preso, que não se mexe |
| Corda esticada (taut rope) | A corda sob tensão, que vai reta e só dobra onde encosta |
| Ponto de dobra (wrap point) | A quina onde a corda esticada muda de direção |
Salve esta página para quando for fazer a sua primeira corda. Tem mais material assim no Cofre, e todo dia sai vídeo novo de tecnologia no @heliofilhou.