1. Renderize na resolução do PS1
Em Project Settings, defina Display > Window > Size > Viewport Width e Height como 320 x 240 e mude Stretch > Mode para viewport. O Godot renderiza o jogo inteiro nesse tamanho e amplia, então cada pixel fica nítido e grosso.
Defina Rendering > Textures > Canvas Textures > Default Texture Filter como Nearest e, em cada material 3D, coloque Texture Filter como Nearest também. Use texturas pequenas: 64 ou 128 px bastam, e o nosso gerador de paleta PSX ajuda a limitar as cores. Para a versão do visual que vale para qualquer engine e para a parte de design, veja como fazer um jogo de terror PSX.
2. Tremor nos vértices com um shader spatial
O PS1 não tinha precisão de subpixel, então os vértices pulavam entre posições da tela. Faça o snap da posição em clip space no vertex() para ter o mesmo tremor:
shader_type spatial;
render_mode diffuse_lambert, specular_disabled;
uniform sampler2D albedo_tex : source_color, filter_nearest;
uniform float snap = 120.0; // lower = more wobble
void vertex() {
vec4 clip = PROJECTION_MATRIX * MODELVIEW_MATRIX * vec4(VERTEX, 1.0);
clip.xy = round(clip.xy / clip.w * snap) / snap * clip.w;
POSITION = clip;
}
void fragment() {
ALBEDO = texture(albedo_tex, UV).rgb;
}3. Neblina e uma lanterna que acaba
Adicione um WorldEnvironment, ligue a Fog e escolha uma neblina escura e levemente colorida. A neblina esconde o fim dos corredores e mantém baixa a contagem de triângulos, o mesmo motivo de os jogos de PS1 a usarem.
Faça da lanterna um SpotLight3D filho da câmera. Gaste a bateria a cada frame e faça a luz piscar quando estiver fraca:
extends SpotLight3D
@export var drain_per_second := 1.5
var battery := 100.0
func _process(delta: float) -> void:
if not visible:
return
battery = max(battery - drain_per_second * delta, 0.0)
light_energy = 0.0 if battery == 0.0 else (randf_range(0.2, 1.0) if battery < 15.0 else 1.0)
func recharge(amount: float) -> void:
battery = min(battery + amount, 100.0)4. Uma ameaça que caça você
Faça o bake de uma NavigationRegion3D no nível, dê ao monstro um NavigationAgent3D e mova-o em direção ao jogador enquanto ele consegue ver ou ouvir:
extends CharacterBody3D
@export var speed := 2.5
@export var player: Node3D
@onready var agent: NavigationAgent3D = $NavigationAgent3D
func _physics_process(_delta: float) -> void:
agent.target_position = player.global_position
var next := agent.get_next_path_position()
velocity = (next - global_position).normalized() * speed
move_and_slide()Adicione esconderijos, uma rota de patrulha e um estado de busca quando ele perde o jogador, e a perseguição começa a parecer justa. O nosso guia de jump scares fala do ritmo.
5. Pule a parte trabalhosa
O Horror Essentials já traz tudo isso funcionando no Godot 4 e no Unity 6: a edição grátis tem movimento, portas e chaves, lanterna com baterias, notas e o filtro PSX; a edição Complete adiciona duas IAs perseguidoras, esconderijos e um sistema de história sem código. Monte o nível com as edições grátis dos nossos kits PSX.
EDIÇÃO GRÁTISHorror Essentials: template de terror PSX para Unity 6 e Godot 4
Unity 6 · URP · código C# + demo
EDIÇÃO GRÁTISPSX Abandoned Hospital: pack modular low poly de terror
EDIÇÃO GRÁTISPSX Forest Horror: kit low poly de acampamento slasher
Perguntas frequentes
Sim. O Godot 4 tem neblina volumétrica, boa iluminação e navegação nativas, e a opção de viewport em baixa resolução facilita o visual de PS1. É grátis e de código aberto.
Renderize em 320x240 com o stretch mode viewport, use filtro nearest, faça o snap dos vértices num shader spatial e coloque neblina.
Um pouco de GDScript, mas os scripts são curtos. O Horror Essentials inclui um sistema de história que monta diálogos e tarefas sem código.
Quem escreveu
Imersa Studios cria os sistemas Unity, packs low poly e guias vendidos no itch.io. O código e as técnicas daqui vêm de lançar esses produtos. Saiba mais sobre o estúdio.
