godot-genre-horror
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGenre: Horror
类型:恐怖
Expert blueprint for horror games balancing tension, atmosphere, and player agency.
恐怖游戏专家蓝图,平衡节奏、氛围与玩家自主性。
NEVER Do (Expert Anti-Patterns)
绝对禁忌(专家级反模式)
Atmosphere & Tension
氛围与节奏
- NEVER maintain 100% tension at all times; strictly use a Sawtooth Pacing model (buildup → peak/scare → dedicated relief period) to prevent player "numbing" and exhaustion.
- NEVER rely on jump-scares as the primary source of horror; focus on atmosphere, spatial audio cues, and the anticipation of a threat to build genuine dread.
- NEVER make environments pitch black to the point of frustrating navigation; darkness should obscure threats (details), not the floor. Use rim lighting or a limited-battery flashlight.
- NEVER grant the player unlimited resources; survival horror relies on Scarcity. Limited battery, rare ammo, and slow animations are mandatory to force stressful decision-making.
- 绝对不要全程保持100%的紧张感;严格采用锯齿形节奏模型(铺垫→峰值/惊吓→专属缓解期),避免玩家产生“麻木感”和疲劳。
- 绝对不要将jump-scare(突脸惊吓)作为恐怖的主要来源;专注于氛围、空间音频线索以及对威胁的“预期”来构建真正的恐惧感。
- 绝对不要让环境黑到让玩家无法顺畅导航;黑暗应遮蔽威胁(细节),而非地面。使用轮廓光或有限电量的手电筒。
- 绝对不要给玩家无限资源;生存恐怖依赖稀缺性。有限的电池、稀有的弹药和缓慢的动画是强制要求,以迫使玩家做出充满压力的决策。
AI & Senses
AI与感知
- NEVER allow AI to detect the player instantly; implement a Suspicion Meter or a 1-3s reaction window before the AI enters full aggression to avoid "unfair cheating" feel.
- NEVER use predictable AI paths; an enemy on a perfect loop is a puzzle, not a predator. Use the Director to periodically "hint" a new destination near the player.
- NEVER use Area3D overlap signals for instant, frame-perfect Line-of-Sight (LoS) checks; use nodeless raycasting via for fixed-physics sync.
PhysicsDirectSpaceState3D.intersect_ray() - NEVER calculate complex AI vision or pathfinding for monsters far outside the camera's frustum; use to disable processing logic.
VisibleOnScreenNotifier3D - NEVER leave navigation avoidance layers unconfigured on chasing monsters; explicitly assign avoidance masks to prevent visual "stacking" in tight corridors.
- 绝对不要让AI瞬间检测到玩家;实现怀疑值计量器或1-3秒的反应窗口,之后AI才会进入完全攻击状态,避免“不公平作弊”的感觉。
- 绝对不要使用可预测的AI路径;完美循环移动的敌人是谜题,而非捕食者。使用Director系统定期“提示”敌人前往玩家附近的新目的地。
- 绝对不要使用Area3D重叠信号进行即时、帧完美的视线(LoS)检测;通过使用无节点射线检测,以实现固定物理同步。
PhysicsDirectSpaceState3D.intersect_ray() - 绝对不要为相机视锥体之外的怪物计算复杂的AI视觉或寻路;使用禁用处理逻辑。
VisibleOnScreenNotifier3D - 绝对不要让追逐怪物的导航避让层未配置;明确分配避让掩码,以避免在狭窄走廊中出现视觉上的“堆叠”。
Technical & Scarcity
技术与稀缺性
- NEVER use the visual SceneTree (like GridContainer children) as the source of truth for inventory; strictly maintain a typed memory structure like .
Dictionary[StringName, Resource] - NEVER rely on instantiating standard Nodes to store base item stats/definitions; use custom scripts to reduce memory overhead and allow direct Inspector editing.
Resource - NEVER forget to call on an item's Resource when adding to inventory; if items have mutable states (ammo/durability), you will overwrite the global resource otherwise.
duplicate(true) - NEVER parse massive JSON save files synchronously; strictly offload heavy parsing to the to prevent auto-save freezes.
WorkerThreadPool - NEVER use standard strings for hot-path IDs (states, item types); strictly use (&"chasing") for pointer-speed comparisons.
StringName - NEVER evaluate exact floating-point equality (sanity == 0.0); strictly use or threshold checks for deterministic triggers.
is_equal_approx() - NEVER write screen-reading shaders expecting Godot 3 ; strictly use
SCREEN_TEXTUREwithsampler2D.hint_screen_texture - NEVER instantiate detailed monster meshes or lights without culling; strictly configure for automatic HLOD efficiency.
visibility_range - NEVER rely on AnimationPlayer for random flickering; use for programmatic, clean energy manipulation.
Tween - NEVER load heavy scare scenes or 4K textures synchronously via ; strictly use
load()to prevent frame stalls.ResourceLoader.load_threaded_request() - NEVER scale CollisionShape3D non-uniformly; strictly adjust internal shape resource parameters (radius, height) to prevent erratic physics.
- 绝对不要将可视化SceneTree(如GridContainer子节点)作为物品栏的数据源;严格使用类型化内存结构,如。
Dictionary[StringName, Resource] - 绝对不要依赖实例化标准Node来存储基础物品属性/定义;使用自定义脚本以减少内存开销,并支持直接在Inspector中编辑。
Resource - 绝对不要忘记在将物品Resource添加到物品栏时调用;如果物品有可变状态(弹药/耐久度),否则会覆盖全局资源。
duplicate(true) - 绝对不要同步解析大型JSON存档文件;严格将繁重的解析任务卸载到,以防止自动存档时出现卡顿。
WorkerThreadPool - 绝对不要将标准字符串用于热路径ID(状态、物品类型);严格使用(&"chasing")以实现指针级速度的比较。
StringName - 绝对不要判断浮点数的精确相等(如sanity == 0.0);严格使用或阈值检查以实现确定性触发。
is_equal_approx() - 绝对不要编写依赖Godot 3中的屏幕读取着色器;严格使用带有
SCREEN_TEXTURE的hint_screen_texture。sampler2D - 绝对不要在不进行剔除的情况下实例化细节丰富的怪物网格或灯光;严格配置以实现自动HLOD效率。
visibility_range - 绝对不要依赖AnimationPlayer实现随机闪烁;使用进行程序化、干净的能量操控。
Tween - 绝对不要通过同步加载大型惊吓场景或4K纹理;严格使用
load()以防止帧停滞。ResourceLoader.load_threaded_request() - 绝对不要非均匀缩放CollisionShape3D;严格调整内部形状资源参数(半径、高度)以避免不稳定的物理效果。
🛠 Expert Components (scripts/)
🛠 专家组件(scripts/)
Original Expert Patterns
原创专家模式
- predator_stalking_ai.gd - Sophisticated "Stalker" AI using dual-brain logic (Director + Senses) and player view-cone avoidance.
- director_pacing.gd - Invisible orchestrator managing the "Sawtooth" tension wave and relief periods.
- predator_stalking_ai.gd - 采用双脑逻辑(Director+感知)和玩家视野锥规避的复杂“追踪者”AI。
- director_pacing.gd - 控制“锯齿形”紧张波和缓解期的隐形协调器。
Modular Components
模块化组件
- monster_los_check.gd - Physics-synced raycasting for high-performance visibility checks.
- flashlight_flicker.gd - Procedural light interference for atmospheric tension.
- inventory_data_storage.gd - Typed data structure for sparse resource management.
- async_scare_loader.gd - Threaded resource loading for hitch-free jump-scares.
- spatial_noise_emitter.gd - Shape-based sound sensing for sensory AI.
- item_state_duplicator.gd - Deep duplication for managing unique weapon/item states.
- fog_claus_intensifier.gd - Volumetric fog manipulation for dread buildup.
- offscreen_logic_suspender.gd - Culling logic for AI processing outside camera view.
- sanity_shader_manager.gd - Instance-uniform driven distortion effects.
- optimized_horror_state_machine.gd - High-speed predator behavior logic.
- monster_los_check.gd - 基于物理同步射线检测的高性能可见性检查。
- flashlight_flicker.gd - 用于氛围紧张感的程序化灯光干扰。
- inventory_data_storage.gd - 用于稀疏资源管理的类型化数据结构。
- async_scare_loader.gd - 用于无卡顿突脸惊吓的线程化资源加载。
- spatial_noise_emitter.gd - 用于感知AI的基于形状的声音检测。
- item_state_duplicator.gd - 用于管理独特武器/物品状态的深度复制。
- fog_claus_intensifier.gd - 用于构建恐惧感的体积雾操控。
- offscreen_logic_suspender.gd - 用于相机视野外AI处理的剔除逻辑。
- sanity_shader_manager.gd - 基于实例uniform的扭曲效果。
- optimized_horror_state_machine.gd - 高速捕食者行为逻辑。
Core Loop
核心循环
- Explore: Player navigates a threatening environment.
- Sense: Player hears/sees signs of danger.
- React: Player hides, runs, or fights (disempowered combat).
- Survive: Player reaches safety or solves a puzzle.
- Relief: Brief moment of calm before tension builds again.
- 探索:玩家在充满威胁的环境中导航。
- 感知:玩家听到/看到危险的迹象。
- 反应:玩家躲藏、逃跑或战斗(弱势战斗)。
- 生存:玩家到达安全区域或解决谜题。
- 缓解:短暂的平静期,之后紧张感再次升级。
Skill Chain
技能链
| Phase | Skills | Purpose |
|---|---|---|
| 1. Atmosphere | | Volumetric fog, dynamic shadows, spatial audio |
| 2. AI | | Hunter AI, sensory perception |
| 3. Player | | Leaning, hiding, slow movement |
| 4. Scarcity | | Limited battery, ammo, health |
| 5. Logic | | The "Director" system controlling pacing |
| 阶段 | 技能 | 目的 |
|---|---|---|
| 1. 氛围 | | 体积雾、动态阴影、空间音频 |
| 2. AI | | 猎手AI、感知 |
| 3. 玩家 | | 侧身、躲藏、缓慢移动 |
| 4. 稀缺性 | | 有限电池、弹药、生命值 |
| 5. 逻辑 | | 控制节奏的“Director”系统 |
Architecture Overview
架构概述
1. The Director System (Macro AI)
1. Director系统(宏观AI)
Controls the pacing of the game to prevent constant exhaustion.
gdscript
undefined控制游戏节奏,避免玩家持续疲劳。
gdscript
undefineddirector.gd
director.gd
extends Node
enum TensionState { BUILDUP, PEAK, RELIEF, QUIET }
var current_tension: float = 0.0
var player_stress_level: float = 0.0
func _process(delta: float) -> void:
match current_tension_state:
TensionState.BUILDUP:
current_tension += 0.5 * delta
if current_tension > 75.0:
trigger_event()
TensionState.RELIEF:
current_tension -= 2.0 * delta
func trigger_event() -> void:
# Hints the Monster AI to check a room NEAR the player, not ON the player
monster_ai.investigate_area(player.global_position + Vector3(randf(), 0, randf()) * 10)
undefinedextends Node
enum TensionState { BUILDUP, PEAK, RELIEF, QUIET }
var current_tension: float = 0.0
var player_stress_level: float = 0.0
func _process(delta: float) -> void:
match current_tension_state:
TensionState.BUILDUP:
current_tension += 0.5 * delta
if current_tension > 75.0:
trigger_event()
TensionState.RELIEF:
current_tension -= 2.0 * delta
func trigger_event() -> void:
# 提示怪物AI检查玩家附近的房间,而非直接在玩家位置
monster_ai.investigate_area(player.global_position + Vector3(randf(), 0, randf()) * 10)
undefined2. Sensory Perception (Micro AI)
2. 感知系统(微观AI)
The monster's actual senses.
gdscript
undefined怪物的真实感知能力。
gdscript
undefinedsensory_component.gd
sensory_component.gd
extends Area3D
signal sound_heard(position: Vector3, volume: float)
signal player_spotted(position: Vector3)
func check_vision(target: Node3D) -> bool:
var space_state = get_world_3d().direct_space_state
var query = PhysicsRayQueryParameters3D.create(global_position, target.global_position)
var result = space_state.intersect_ray(query)
if result and result.collider == target:
return true
return falseundefinedextends Area3D
signal sound_heard(position: Vector3, volume: float)
signal player_spotted(position: Vector3)
func check_vision(target: Node3D) -> bool:
var space_state = get_world_3d().direct_space_state
var query = PhysicsRayQueryParameters3D.create(global_position, target.global_position)
var result = space_state.intersect_ray(query)
if result and result.collider == target:
return true
return falseundefined3. Sanity / Stress System
3. 理智/压力系统
Distorting the world based on fear.
gdscript
undefined基于恐惧扭曲游戏世界。
gdscript
undefinedsanity_manager.gd
sanity_manager.gd
func update_sanity(amount: float) -> void:
current_sanity = clamp(current_sanity + amount, 0.0, 100.0)
# Effect: Camera Shake
camera_shake_intensity = (100.0 - current_sanity) * 0.01
# Effect: Audio Distortion
audio_bus.get_effect(0).drive = (100.0 - current_sanity) * 0.05
undefinedfunc update_sanity(amount: float) -> void:
current_sanity = clamp(current_sanity + amount, 0.0, 100.0)
# 效果:相机抖动
camera_shake_intensity = (100.0 - current_sanity) * 0.01
# 效果:音频失真
audio_bus.get_effect(0).drive = (100.0 - current_sanity) * 0.05
undefinedKey Mechanics Implementation
核心机制实现
Pacing (The Sawtooth Wave)
节奏(锯齿波)
Horror needs peaks and valleys.
- Safety: Save room.
- Unease: Strange noise, lights flicker.
- Dread: Monster is known to be close.
- Terror: Chase sequence / Combat.
- Relief: Escape to Safety.
恐怖游戏需要高峰和低谷。
- 安全:存档室。
- 不安:奇怪的声音、灯光闪烁。
- 恐惧:已知怪物就在附近。
- 恐怖:追逐序列/战斗。
- 缓解:逃到安全区域。
The "Dual Brain" AI
“双脑”AI
- Director (All-knowing): Cheats to keep the alien relevant (teleports it closer if far away, guides it to player's general area).
- Alien (Senses only): Honest AI. Must actually see/hear the player to attack.
- Director(全知):通过作弊保持怪物的存在感(如果距离过远则将其传送到附近,引导其前往玩家大致区域)。
- 怪物(仅感知):真实AI。必须实际看到/听到玩家才会发起攻击。
Godot-Specific Tips
Godot专属技巧
- Volumetric Fog: Use ->
WorldEnvironmentfor instant atmosphere. AnimateVolumetricFogfor dynamic dread.density - Light Occluder 2D: For 2D horror, shadow casting is essential.
- AudioBus: Use and
Reverbon the Master bus, controlled by scripts, to simulate "muffled" hearing when scared or hiding.LowPassFilter - AnimationTree: Use blend spaces to smooth transitions between "Sneak", "Walk", and "Run" animations.
- 体积雾:使用->
WorldEnvironment快速营造氛围。动画化VolumetricFog以实现动态恐惧效果。density - Light Occluder 2D:对于2D恐怖游戏,阴影投射至关重要。
- AudioBus:在主总线使用和
Reverb,通过脚本控制,模拟恐惧或躲藏时的“闷响”听觉效果。LowPassFilter - AnimationTree:使用混合空间平滑“Sneak(潜行)”、“Walk(行走)”和“Run(奔跑)”动画之间的过渡。
Common Pitfalls
常见陷阱
- Constant Tension: Player gets numb. Fix: Enforce "Relief" periods where nothing happens.
- Frustrating AI: AI sees player instantly. Fix: Give AI a "reaction time" or "suspicion meter" before full aggro.
- Too Dark: Player can't see anything. Fix: Darkness should obscure details, not navigation. Use rim lighting or a weak flashlight.
- 持续紧张:玩家会麻木。解决方法:强制执行“缓解”期,期间无任何事件发生。
- 令人沮丧的AI:AI瞬间看到玩家。解决方法:给AI一个“反应时间”或“怀疑值计量器”,之后再进入完全攻击状态。
- 过暗:玩家什么都看不见。解决方法:黑暗应遮蔽细节,而非导航。使用轮廓光或弱手电筒。
Reference
参考
- Master Skill: godot-master
- 大师技能:godot-master