1. Renderiza a la resolución de PS1
En Project Settings, pon Display > Window > Size > Viewport Width y Height en 320 x 240 y cambia Stretch > Mode a viewport. Godot renderiza todo el juego a ese tamaño y lo amplía, así que cada píxel queda nítido y grueso.
Pon Rendering > Textures > Canvas Textures > Default Texture Filter en Nearest y, en cada material 3D, Texture Filter en Nearest también. Usa texturas pequeñas: 64 o 128 px bastan, y nuestro generador de paleta PSX ayuda a limitar los colores. Para la versión de la estética que sirve en cualquier motor y la parte de diseño, mira cómo hacer un juego de terror PSX.
2. Temblor en los vértices con un shader spatial
La PS1 no tenía precisión de subpíxel, así que los vértices saltaban entre posiciones de la pantalla. Ajusta la posición en clip space dentro de vertex() para conseguir el mismo temblor:
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. Niebla y una linterna que se agota
Añade un WorldEnvironment, activa Fog y elige una niebla oscura y algo coloreada. La niebla oculta el final de los pasillos y mantiene bajo el número de triángulos, la misma razón por la que la usaban los juegos de PS1.
Haz que la linterna sea un SpotLight3D hijo de la cámara. Gasta la batería cada frame y haz que parpadee cuando esté baja:
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. Una amenaza que te caza
Haz el bake de una NavigationRegion3D en el nivel, dale al monstruo un NavigationAgent3D y muévelo hacia el jugador mientras pueda verlo u oírlo:
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()Añade escondites, una ruta de patrulla y un estado de búsqueda cuando pierde al jugador, y la persecución empieza a sentirse justa. Nuestra guía de jump scares habla del ritmo.
5. Sáltate la parte pesada
Horror Essentials ya trae todo esto funcionando en Godot 4 y Unity 6: la edición gratis tiene movimiento, puertas y llaves, linterna con baterías, notas y el filtro PSX; la edición Complete añade dos IA perseguidoras, escondites y un sistema de historia sin código. Arma el nivel con las ediciones gratis de nuestros kits PSX.
EDICIÓN GRATISHorror Essentials: plantilla de terror PSX para Unity 6 y Godot 4
Unity 6 · URP · código C# + demo
EDICIÓN GRATISPSX Abandoned Hospital: pack modular low poly de terror
EDICIÓN GRATISPSX Forest Horror: kit low poly de campamento slasher
Preguntas frecuentes
Sí. Godot 4 trae niebla volumétrica, buena iluminación y navegación integradas, y la opción de viewport a baja resolución facilita la estética de PS1. Es gratis y de código abierto.
Renderiza a 320x240 con el stretch mode viewport, usa filtro nearest, ajusta los vértices en un shader spatial y añade niebla.
Algo de GDScript, pero los scripts son cortos. Horror Essentials incluye un sistema de historia que arma diálogos y tareas sin código.
Quién lo escribió
Imersa Studios crea los sistemas Unity, los packs low poly y las guías que se venden en itch.io. El código y las técnicas de aquí salen de publicar esos productos. Más sobre el estudio.
