Como implementar pedra é objeto na prática
Você provavelmente já viu jogos onde pedras no chão são apenas texturas coladas no terreno ou sprites estáticos que o jogador atravessa. Isso funciona até o momento em que alguém quer interagir com elas, e aí tudo desmorona. A filosofia de pedra é objeto resolve isso tratando cada elemento do cenário como um objeto computacional com comportamento próprio.
O que exatamente significa pedra é objeto
Significa simplesmente que tudo que existe no mundo do jogo — incluindo pedras, troncos, caixas, vasos — deve ser instanciado como um objeto com propriedades físicas, colisão, e capacidade de resposta a ações. Não é uma técnica avançada. É uma decisão de arquitetura que muda tudo o resto. No meu primeiro projeto sério, fiz isso errado. Criei trinta e sete pedras diferentes como meshes estáticos no Unity. Quando o designer pediu para elas serem empurráveis, precisei refazer todo o pipeline. Demorei três dias inteiros porque esqueci de adicionar colisor a doze delas e os scripts de interação quebravam por falta de tag padronizada. Se eu tivesse aplicado pedra é objeto desde o início, isso não teria acontecido.
Implementação passo a passo
O processo básico envolve três camadas. Primeiro, a definição do objeto. Segundo, a resposta física. Terceiro, a interação com o jogador.
Passo 1: Definir a classe base do objeto
Crie uma classe base que herde de MonoBehaviour e contenha os campos comuns a todos os objetos interativos. No meu caso, eu uso algo assim: public class GameObjectBase : MonoBehaviour
{
public float massa = 1f;
public bool empurravel = true;
public float forcaDeEmpurrao = 5f;
public bool destrutivel = false;
public int vida = 1;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
if (rb == null) AddComponent<Rigidbody>();
rb.mass = massa;
rb.freezeRotation = true;
}
}
Perceba o detalhe importante: eu verifico se o Rigidbody já existe antes de adicionar. Se você estiver trabalhando com assets importados de modelagem 3D, muitos vêm com física integrada mal configurada. Deixar isso acontecer gera objetos que escapam do mapa ou treman descontroladamente.
Passo 2: Configurar colisões corretamente
Aqui é onde a maioria dos iniciantes erra. Eles colocam um collider genérico em volta do modelo inteiro. Isso funciona para objetos simples, mas para geometria irregular como pedras, o resultado é imprevisível. A solução prática é usar múltiplos colliders simplificados. Para uma pedra média de jogo, dois BoxCollider sobrepostos ou um MeshCollider com convexo resolve. Evite MeshCollider sem convexo em objetos dinâmicos — o custo computacional sobe exponencialmente e seu jogo vai travar em qualquer cena com mais de dez desses objetos na tela.
Eu tenho um caso específico que merece ser dito: em um projeto de survival, coloquei MeshCollider convexo em uma pedra grande. O jogador conseguia empurrá-la normalmente, mas quando caía de um penhasco, ela se fragmentava visualmente e os pedaços passavam a atravessar paredes. O problema era que o MeshCollider gerencia mal colisão com geometria dinâmica após destruição de prefab. A correção foi substituir por quatro BoxCollider pequenos para os fragmentos e ajustar o material de fricção para 0.4.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Passo 3: Interação com o jogador
O script de interação deve estar separado da classe base. Use interface ou herança diferente. Eu prefiro interface porque objetos podem precisar reagir de formas distintas — uma pedra reage sendo empurrada, uma arma reage sendo sacada, um baú reage sendo aberto. Na prática, o código fica mais ou menos assim:
public class Interagivel : MonoBehaviour
{
public virtual void Interagir(Jogador jogador) { }
}
public class PedraInteragivel : GameObjectBase, Interagivel
{
public void Interagir(Jogador jogador)
{
if (empurravel)
{
rb.AddForce(jogador.transform.forward * forcaDeEmpurrao, ForceMode.Impulse);
}
}
}
Erros comuns que você vai cometer
O primeiro erro é esquecer de desativar a rotação nos eixos X e Z do Rigidbody. Objetos que devem apenas deslizar pelo chão acabam tombando e girando de forma feia. Trave a rotação exceto se o objeto precisar rolar ativamente. O segundo erro é tratar todas as pedras como iguais. Uma pedra pequena no caminho do jogador deve ter massa menor que uma pedra grande perto de uma ponte. A diferença de massa afeta diretamente a força necessária para empurrar e a distância que o objeto é arremessado. Teste isso no editor antes de enviar para build.
O terceiro erro, e o mais caro, é não padronizar tags e layers. Quando você tem cinquenta pedras espalhadas pelo mapa e decide que agora elas podem ser destruídas, encontrar todas elas para aplicar um novo script leva mais tempo do que configurar o sistema certo desde o começo. Use uma tag chamada "PedraObjeto" e um layer separado para objetos do cenário.
Limitações desta abordagem
Pedra é objeto funciona bem para cenários com até cem objetos interativos simultâneos. Acima disso, o custo de física começa a pesar. Se o seu jogo precisa de milhares de pedras em um terreno aberto, considere usar instância procedural com LOD físico — objetos distantes recebem colliders simplificados ou são removidos completamente da simulação. Também não é adequada para jogos puramente narrativos onde interações com o cenário são raras. Nesse caso, gambis de collider manual ou triggers fixos resolvem mais rápido e gastam menos tempo de desenvolvimento.
Se o seu projeto é 2D e o conceito de pedra é objeto se aplica de forma diferente, a lógica permanece a mesma mas a implementação usa Physics2D em vez de Rigidbody. A estrutura de classes base e interfaces continua válida.
Download do kit de exemplo
Não tenho um link de download próprio para disponibilizar aqui, mas o padrão de implementação que descrevi é simples o suficiente para ser copiado e adaptado. O essencial é começar pela classe base, testar com três pedras no editor antes de espalhar pelo mapa, e nunca esquecer de verificar colisões depois de qualquer modificação no prefab.