godot-genre-romance

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Genre: Romance & Dating Sim

类型:恋爱与约会模拟

Romance games are built on the "Affection Economy"—the management of player time and resources to influence NPC attraction, trust, and intimacy.
恋爱游戏基于「好感度经济」构建——即玩家通过管理自身时间与资源,来提升NPC的好感、信任与亲密程度。

Core Loop

核心循环

  1. Meet: Encounter potential love interests and establish baseline rapport.
  2. Date: Engage in structured events to learn preferences and test compatibility.
  3. Deepen: Invest resources (time, gifts, choices) to increase affection/stats.
  4. Branch: Story diverges into character-specific "Routes" based on major milestones.
  5. Resolve: Reach a specialized ending (Good/Normal/Bad) based on relationship quality.
  1. 相遇:邂逅潜在恋爱对象,建立基础好感。
  2. 约会:参与结构化事件,了解对方偏好并测试适配度。
  3. 升温:投入资源(时间、礼物、选择)提升好感/相关属性。
  4. 分支:根据关键里程碑,剧情分化为角色专属「路线」。
  5. 结局:根据关系质量达成对应结局(好/普通/坏)。

NEVER Do in Romance Games

恋爱游戏绝对禁忌

  • NEVER create "Vending Machine" romance — If giving 10 gifts always equals a confession, the characters feel like objects. ALWAYS incorporate variables like current mood, timing, and stat thresholds (e.g., "Must have 10 Courage to ask out").
  • NEVER use 100% opaque stats — If the player doesn't know why they failed a date, they feel cheated. ALWAYS provide subtle feedback or visible "Relationship Screens" (e.g., hearts pulsing, trust bars filling).
  • NEVER use binary Affection (Love/Hate) — Real relationships are complex. Use multi-axis stats such as Attraction (physical/chemistry), Trust (emotional safety), and Comfort (familiarity) for deeper simulation.
  • NEVER use the "Same Date Order" trap — Repeating the exact same date sequence for every character makes the game feel repetitive. ALWAYS vary date locations, activities, and dialogue structures per love interest.
  • NEVER forget "Missable" Milestones — If a player misses the "Valentine's Day" event because they were working, that's a meaningful (if painful) consequence. Don't force every event to happen regardless of player choices.
  • NEVER ignore NPC Autonomy — If an NPC only exists for the player, they feel hollow. Give them their own schedules, goals, and the ability to reject the player if specific conditions (like low trust) aren't met.

PhaseSkillsPurpose
1. Stats
dictionaries
,
resources
Tracking multi-axis affection, character profiles
2. Timeline
autoload-architecture
,
signals
Managing time/days, triggering scheduled dates
3. Narrative
godot-dialogue-system
,
visual-novel
Conversational branching and choice consequence
4. Persistence
godot-save-load-systems
Saving relationship states, CG gallery, flags
5. Aesthetics
ui-theming
,
godot-tweening
Heart-themed UI, blushing effects, emotive icons
  • 绝对不要做「自动贩卖机式」恋爱 — 如果送10份礼物就必然触发告白,角色会显得像没有感情的物品。必须加入当前心情、时机、属性阈值等变量(例如「需达到10点勇气值才能发起邀约」)。
  • 绝对不要使用100%不透明的属性 — 如果玩家完全不知道约会失败的原因,会产生被欺骗的感受。必须提供微妙的反馈,或者可见的「关系界面」(例如跳动的爱心、增长的信任进度条)。
  • 绝对不要使用二元好感度(爱/恨) — 现实中的关系非常复杂。使用多维度属性例如吸引力(外表/化学反应)、信任(情绪安全感)、舒适感(熟悉度)来实现更有深度的模拟。
  • 绝对不要陷入「千篇一律约会顺序」陷阱 — 所有角色都使用完全相同的约会序列会让游戏显得非常重复。必须为每个恋爱对象设计不同的约会地点、活动和对话结构。
  • 绝对不要忽略「可错过」的里程碑 — 如果玩家因为忙于打工错过了「情人节」活动,这是一个有意义(哪怕令人遗憾)的后果。不要无视玩家的选择,强制触发所有事件。
  • 绝对不要忽视NPC自主性 — 如果NPC的存在完全只为服务玩家,会显得非常空洞。要给NPC设置专属的日程、目标,当特定条件(例如信任度过低)不满足时,NPC可以拒绝玩家。

阶段技能用途
1. 属性
dictionaries
,
resources
追踪多维度好感度、角色档案
2. 时间线
autoload-architecture
,
signals
管理时间/天数,触发预定约会
3. 叙事
godot-dialogue-system
,
visual-novel
对话分支与选择后果处理
4. 持久化
godot-save-load-systems
保存关系状态、CG画廊、标记位
5. 视觉表现
ui-theming
,
godot-tweening
爱心主题UI、脸红效果、情绪图标

Architecture Overview

架构概览

1. Affection Manager (The Heart)

1. 好感度管理器(核心模块)

Handles complex relationship stats and gift preferences for all characters.
gdscript
undefined
处理所有角色的复杂关系属性与礼物偏好逻辑。
gdscript
undefined

affection_manager.gd

affection_manager.gd

class_name AffectionManager extends Node
signal milestone_reached(character_id, level)
var relationship_data: Dictionary = {} # character_id: { attraction: 0, trust: 0, comfort: 0 }
func add_affection(char_id: String, type: String, amount: int) -> void: if not relationship_data.has(char_id): relationship_data[char_id] = {"attraction": 0, "trust": 0, "comfort": 0}
relationship_data[char_id][type] = clamp(relationship_data[char_id][type] + amount, -100, 100)
check_milestones(char_id)
func get_gift_effect(char_id: String, item_id: String) -> int: # Logic for likes/dislikes with diminishing returns return 10 # Placeholder
undefined
class_name AffectionManager extends Node
signal milestone_reached(character_id, level)
var relationship_data: Dictionary = {} # character_id: { attraction: 0, trust: 0, comfort: 0 }
func add_affection(char_id: String, type: String, amount: int) -> void: if not relationship_data.has(char_id): relationship_data[char_id] = {"attraction": 0, "trust": 0, "comfort": 0}
relationship_data[char_id][type] = clamp(relationship_data[char_id][type] + amount, -100, 100)
check_milestones(char_id)
func get_gift_effect(char_id: String, item_id: String) -> int: # Logic for likes/dislikes with diminishing returns return 10 # Placeholder
undefined

2. Date Event System

2. 约会事件系统

Manages the success or failure of romantic outings.
gdscript
undefined
管理浪漫出行的成功或失败逻辑。
gdscript
undefined

date_event_system.gd

date_event_system.gd

func run_date(character_id: String, location_res: DateLocation) -> void: var score = 0 # Weighted calculation score += relationship_data[character_id]["attraction"] * location_res.chemistry_mod score += relationship_data[character_id]["trust"] * location_res.safety_mod
if score > location_res.success_threshold:
    play_date_outcome("SUCCESS", character_id)
else:
    play_date_outcome("FAILURE", character_id)
undefined
func run_date(character_id: String, location_res: DateLocation) -> void: var score = 0 # Weighted calculation score += relationship_data[character_id]["attraction"] * location_res.chemistry_mod score += relationship_data[character_id]["trust"] * location_res.safety_mod
if score > location_res.success_threshold:
    play_date_outcome("SUCCESS", character_id)
else:
    play_date_outcome("FAILURE", character_id)
undefined

3. Route Manager

3. 路线管理器

Controls story branching and persistent unlocks.
gdscript
undefined
控制剧情分支与持久化解锁内容。
gdscript
undefined

route_manager.gd

route_manager.gd

var unlocked_routes: Array[String] = []
func lock_in_route(char_id: String): # Detect conflicts with other routes here if flags.get("on_route"): return
current_route = char_id
flags["on_route"] = true
unlocked_cgs.append(char_id + "_prologue")
undefined
var unlocked_routes: Array[String] = []
func lock_in_route(char_id: String): # Detect conflicts with other routes here if flags.get("on_route"): return
current_route = char_id
flags["on_route"] = true
unlocked_cgs.append(char_id + "_prologue")
undefined

Key Mechanics Implementation

核心机制实现

Emotional Feedback (Juice)

情绪反馈(爽感设计)

Don't just change a number; show the change.
gdscript
undefined
不要只修改数值,要将变化可视化展示给玩家。
gdscript
undefined

ui_feedback.gd

ui_feedback.gd

func play_heart_burst(pos: Vector2): var heart = heart_scene.instantiate() add_child(heart) heart.global_position = pos var tween = create_tween().set_parallel() tween.tween_property(heart, "scale", Vector2(1.5, 1.5), 0.5) tween.tween_property(heart, "modulate:a", 0.0, 0.5)
undefined
func play_heart_burst(pos: Vector2): var heart = heart_scene.instantiate() add_child(heart) heart.global_position = pos var tween = create_tween().set_parallel() tween.tween_property(heart, "scale", Vector2(1.5, 1.5), 0.5) tween.tween_property(heart, "modulate:a", 0.0, 0.5)
undefined

Time-Gated Events

时间锁事件

Romance thrives on anticipation.
  • Deadline Scheduling: "Confess by June 15th or lose."
  • Contextual Dialogue: Characters reacting differently based on time of day or weather.
浪漫感源于期待感。
  • 截止日安排:「6月15日前必须告白,否则失败」。
  • 上下文对话:角色会根据时段或天气给出不同的反应。

Common Pitfalls

常见陷阱

  1. The "Pervert" Trap: Forcing the player to always pick the flirtiest option to win. Fix: Allow "Trust" and "Friendship" paths to lead to romance eventually.
  2. Opaque Success: Failing a date without knowing why. Fix: Use character dialogue to hint at preferences ("I'm not really a fan of loud places...").
  3. Route Conflict: Accidentally dating two people with zero consequences. Fix: Implement a "Jealousy" or "Conflict Detection" system in the Route Manager.
  1. 「变态选项」陷阱:强迫玩家每次都选最轻浮的选项才能攻略成功。修复方案:允许「信任」和「友谊」路线最终也能走向恋爱结局。
  2. 不透明的成功判定:约会失败却完全不知道原因。修复方案:通过角色对话暗示偏好(例如「我其实不太喜欢吵闹的地方...」)。
  3. 路线冲突:同时和多名角色约会却没有任何后果。修复方案:在路线管理器中实现「嫉妒」或「冲突检测」系统。

Godot-Specific Tips

Godot专属开发提示

  • Resources for Characters: Use
    CharacterProfile
    resources to store base stats, sprites, and gift preferences.
  • RichTextLabel Animations: Use custom BBCode for "blushing" text (pulsing pink) or "nervous" text (shaking).
  • Dialogic Integration: While this skill focuses on the systems, pairing it with Godot's Dialogic plugin is highly recommended for handling the actual dialogue boxes.
  • 角色资源管理:使用
    CharacterProfile
    资源存储基础属性、 sprite、礼物偏好。
  • RichTextLabel动画:使用自定义BBCode实现「脸红」文本(跳动的粉色)或者「紧张」文本(抖动效果)。
  • Dialogic集成:虽然本技能重点关注系统层面的实现,但非常推荐搭配Godot的Dialogic插件来处理实际的对话框逻辑。

Reference

参考

  • Master Skill: godot-master
  • Sub-specialty: godot-genre-visual-novel
  • 主技能:godot-master
  • 子方向:godot-genre-visual-novel