godot-genre-romance
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGenre: 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
核心循环
- Meet: Encounter potential love interests and establish baseline rapport.
- Date: Engage in structured events to learn preferences and test compatibility.
- Deepen: Invest resources (time, gifts, choices) to increase affection/stats.
- Branch: Story diverges into character-specific "Routes" based on major milestones.
- Resolve: Reach a specialized ending (Good/Normal/Bad) based on relationship quality.
- 相遇:邂逅潜在恋爱对象,建立基础好感。
- 约会:参与结构化事件,了解对方偏好并测试适配度。
- 升温:投入资源(时间、礼物、选择)提升好感/相关属性。
- 分支:根据关键里程碑,剧情分化为角色专属「路线」。
- 结局:根据关系质量达成对应结局(好/普通/坏)。
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.
| Phase | Skills | Purpose |
|---|---|---|
| 1. Stats | | Tracking multi-axis affection, character profiles |
| 2. Timeline | | Managing time/days, triggering scheduled dates |
| 3. Narrative | | Conversational branching and choice consequence |
| 4. Persistence | | Saving relationship states, CG gallery, flags |
| 5. Aesthetics | | Heart-themed UI, blushing effects, emotive icons |
- 绝对不要做「自动贩卖机式」恋爱 — 如果送10份礼物就必然触发告白,角色会显得像没有感情的物品。必须加入当前心情、时机、属性阈值等变量(例如「需达到10点勇气值才能发起邀约」)。
- 绝对不要使用100%不透明的属性 — 如果玩家完全不知道约会失败的原因,会产生被欺骗的感受。必须提供微妙的反馈,或者可见的「关系界面」(例如跳动的爱心、增长的信任进度条)。
- 绝对不要使用二元好感度(爱/恨) — 现实中的关系非常复杂。使用多维度属性例如吸引力(外表/化学反应)、信任(情绪安全感)、舒适感(熟悉度)来实现更有深度的模拟。
- 绝对不要陷入「千篇一律约会顺序」陷阱 — 所有角色都使用完全相同的约会序列会让游戏显得非常重复。必须为每个恋爱对象设计不同的约会地点、活动和对话结构。
- 绝对不要忽略「可错过」的里程碑 — 如果玩家因为忙于打工错过了「情人节」活动,这是一个有意义(哪怕令人遗憾)的后果。不要无视玩家的选择,强制触发所有事件。
- 绝对不要忽视NPC自主性 — 如果NPC的存在完全只为服务玩家,会显得非常空洞。要给NPC设置专属的日程、目标,当特定条件(例如信任度过低)不满足时,NPC可以拒绝玩家。
| 阶段 | 技能 | 用途 |
|---|---|---|
| 1. 属性 | | 追踪多维度好感度、角色档案 |
| 2. 时间线 | | 管理时间/天数,触发预定约会 |
| 3. 叙事 | | 对话分支与选择后果处理 |
| 4. 持久化 | | 保存关系状态、CG画廊、标记位 |
| 5. 视觉表现 | | 爱心主题UI、脸红效果、情绪图标 |
Architecture Overview
架构概览
1. Affection Manager (The Heart)
1. 好感度管理器(核心模块)
Handles complex relationship stats and gift preferences for all characters.
gdscript
undefined处理所有角色的复杂关系属性与礼物偏好逻辑。
gdscript
undefinedaffection_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
undefinedclass_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
undefined2. Date Event System
2. 约会事件系统
Manages the success or failure of romantic outings.
gdscript
undefined管理浪漫出行的成功或失败逻辑。
gdscript
undefineddate_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)undefinedfunc 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)undefined3. Route Manager
3. 路线管理器
Controls story branching and persistent unlocks.
gdscript
undefined控制剧情分支与持久化解锁内容。
gdscript
undefinedroute_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")undefinedvar 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")undefinedKey Mechanics Implementation
核心机制实现
Emotional Feedback (Juice)
情绪反馈(爽感设计)
Don't just change a number; show the change.
gdscript
undefined不要只修改数值,要将变化可视化展示给玩家。
gdscript
undefinedui_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)
undefinedfunc 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)
undefinedTime-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
常见陷阱
- 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.
- 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...").
- Route Conflict: Accidentally dating two people with zero consequences. Fix: Implement a "Jealousy" or "Conflict Detection" system in the Route Manager.
- 「变态选项」陷阱:强迫玩家每次都选最轻浮的选项才能攻略成功。修复方案:允许「信任」和「友谊」路线最终也能走向恋爱结局。
- 不透明的成功判定:约会失败却完全不知道原因。修复方案:通过角色对话暗示偏好(例如「我其实不太喜欢吵闹的地方...」)。
- 路线冲突:同时和多名角色约会却没有任何后果。修复方案:在路线管理器中实现「嫉妒」或「冲突检测」系统。
Godot-Specific Tips
Godot专属开发提示
- Resources for Characters: Use resources to store base stats, sprites, and gift preferences.
CharacterProfile - 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.
- 角色资源管理:使用资源存储基础属性、 sprite、礼物偏好。
CharacterProfile - RichTextLabel动画:使用自定义BBCode实现「脸红」文本(跳动的粉色)或者「紧张」文本(抖动效果)。
- Dialogic集成:虽然本技能重点关注系统层面的实现,但非常推荐搭配Godot的Dialogic插件来处理实际的对话框逻辑。
Reference
参考
- Master Skill: godot-master
- Sub-specialty: godot-genre-visual-novel
- 主技能:godot-master
- 子方向:godot-genre-visual-novel