游戏叙事 (Game Narrative) 不仅仅是”讲故事”,而是通过多种媒介(对话、环境、机制、UI)向玩家传达世界观、角色动机和情感体验。
对于非剧情驱动型游戏(如塔防、Roguelike、Looter),叙事的作用是:
通过明确的文本、对话、过场动画传递:
强度等级:
5 级: 完整剧情(RPG,如《巫师 3》)
4 级: 关键剧情节点(如《Hades》每次逃脱后的对话)
3 级: 碎片化剧情(如《黑暗之魂》物品描述)
2 级: 极简背景设定(如《Vampire Survivors》开场字幕)
1 级: 无显性叙事(如《俄罗斯方块》)
推荐 Vampirefall 选择: 2-3 级(碎片化 + 极简)
通过场景、道具、美术风格传递信息:
经典案例:
设计公式:
环境叙事强度 = (视觉细节密度 × 暗示清晰度) ÷ 玩家注意力需求
优秀设计:
- 视觉细节: 丰富但不杂乱
- 暗示清晰度: 70% 玩家能理解
- 注意力需求: 低(不影响战斗)
游戏规则本身就是叙事工具:
| 游戏 | 机制 | 叙事含义 |
|---|---|---|
| Dark Souls | 死亡重生 | “你是不死人,永远被诅咒” |
| Hades | 逃脱失败 | “你永远无法逃离冥界” |
| Vampire Survivors | 30 分钟死亡 | “死神最终会降临” |
| Loop Hero | 循环地图 | “你被困在时间循环中” |
Vampirefall 潜在机制叙事:
Roguelike 类游戏面临独特问题:玩家会重复体验同一内容 50+ 次。
传统叙事的问题:
解决方案:
graph TD
A[肉鸽叙事设计] --> B[动态对话系统]
A --> C[渐进式剧情揭露]
A --> D[玩家驱动的叙事]
B --> B1[基于进度的新对话]
B --> B2[基于失败次数的反馈]
C --> C1[每次 Run 解锁新 Lore]
C --> C2[收集品拼凑完整故事]
D --> D1[玩家选择分支]
D --> D2[Build 影响台词]
叙事密度公式:
叙事密度 = 叙事内容总量 / 玩家游玩时间
过高 (>0.3): 干扰玩法(日式 RPG)
适中 (0.1-0.3): 平衡(Hades)
过低 (<0.1): 缺乏代入感(纯数值游戏)
推荐 Vampirefall: 0.15 左右
实践建议:
# 世界观一句话描述
"最后的吸血鬼猎人,在堕落的王国中建立防线,对抗无尽的暗夜军团。"
# 核心冲突
玩家 (守护者) vs 吸血鬼大军 (入侵者)
# 独特设定
- 塔防要素:玩家建造"圣光塔"净化区域
- 肉鸽要素:每次轮回都是"不同的猎人后代"
- Looter 要素:收集"失落的圣物"变强
# 情感基调
黑暗但不绝望,史诗但不沉重(参考《暗黑破坏神》)
┌─────────────────────────────────────┐
│ 第 1 层:核心循环包装(必须) │
│ - 为什么要建塔?(保护圣地) │
│ - 为什么要战斗?(净化暗夜) │
├─────────────────────────────────────┤
│ 第 2 层:角色与装备 Lore(推荐) │
│ - 每个装备有简短描述 │
│ - Boss 有背景故事 │
├─────────────────────────────────────┤
│ 第 3 层:深度世界观(可选) │
│ - 图鉴系统解锁完整历史 │
│ - 隐藏区域揭示真相 │
└─────────────────────────────────────┘
[System.Serializable]
public class LoreEntry
{
public string loreID;
public LoreCategory category;
[Header("基础信息")]
public string title = "失落的圣剑";
[TextArea(3, 10)]
public string shortDescription = "曾属于第一位猎人的武器。";
[TextArea(5, 15)]
public string fullLore = "在暗夜降临之前,这把剑曾斩杀了无数恶魔...";
[Header("解锁条件")]
public UnlockCondition unlockCondition;
public int requiredProgress = 0;
[Header("奖励(可选)")]
public bool grantsReward = false;
public RewardData reward;
}
public enum LoreCategory
{
Weapon, // 武器传说
Enemy, // 敌人背景
Location, // 地点历史
Character, // 角色故事
WorldEvent // 世界事件
}
public enum UnlockCondition
{
AlwaysAvailable, // 始终可见
DefeatBoss, // 击败特定 Boss
CollectItem, // 收集特定物品
ReachLevel, // 达到等级
CompleteRuns // 完成 N 次 Run
}
public class DialogueSystem : MonoBehaviour
{
private Dictionary<string, List<DialogueLine>> characterDialogues;
private Dictionary<string, int> dialogueProgress; // 追踪对话进度
public DialogueLine GetDialogue(string characterID, GameContext context)
{
// 1. 获取角色的对话池
if (!characterDialogues.ContainsKey(characterID))
return null;
var lines = characterDialogues[characterID];
// 2. 根据上下文筛选
var validLines = lines.Where(line => line.MatchContext(context)).ToList();
if (validLines.Count == 0)
return GetFallbackDialogue(characterID);
// 3. 优先级排序(新对话 > 通用对话)
validLines = validLines.OrderByDescending(line => line.priority).ToList();
// 4. 返回未见过的对话(如果有)
int progress = dialogueProgress.GetValueOrDefault(characterID, 0);
if (progress < validLines.Count)
{
var newLine = validLines[progress];
dialogueProgress[characterID] = progress + 1;
return newLine;
}
// 5. 所有对话都见过,返回随机通用对话
return validLines[Random.Range(0, validLines.Count)];
}
}
[System.Serializable]
public class DialogueLine
{
public string text;
public int priority = 0; // 优先级(新对话高优先级)
[Header("上下文条件")]
public int minRunsCompleted = 0;
public int maxRunsCompleted = 999;
public int minConsecutiveDeaths = 0;
public bool requiresBossDefeated = false;
public string requiredBossID;
public bool MatchContext(GameContext context)
{
if (context.runsCompleted < minRunsCompleted ||
context.runsCompleted > maxRunsCompleted)
return false;
if (context.consecutiveDeaths < minConsecutiveDeaths)
return false;
if (requiresBossDefeated && !context.defeatedBosses.Contains(requiredBossID))
return false;
return true;
}
}
[System.Serializable]
public class ItemLore
{
[Header("名称设计")]
public string itemName = "暗影猎弓";
public string subtitle = "月光下的复仇"; // 可选副标题
[Header("描述层次")]
[TextArea(2, 5)]
public string mechanicsDesc = "攻击速度 +30%\n暴击率 +15%"; // 数值描述
[TextArea(2, 5)]
public string flavorText = "\"在黑暗中,我们是光明。\" - 猎人信条"; // 风味文本
[Header("隐藏 Lore(需解锁)")]
[TextArea(5, 10)]
public string hiddenLore = "这把弓曾属于暗影猎人艾莉娅...";
public bool loreUnlocked = false;
}
最佳实践:
[System.Serializable]
public class EnemyBestiary
{
public string enemyID;
public string displayName = "暗夜行者";
[Header("基础信息")]
[TextArea(2, 5)]
public string basicInfo = "吸血鬼的低阶仆从,失去了人性。";
[Header("战术信息(击杀 N 次后解锁)")]
public int killsToUnlockTactics = 10;
[TextArea(3, 6)]
public string tacticalInfo = "弱点:圣光伤害\n抗性:物理攻击";
[Header("深度 Lore(击杀 Boss 后解锁)")]
public string requiredBossDefeat;
[TextArea(5, 10)]
public string deepLore = "他们曾是王国的守卫,如今沦为怪物...";
// 解锁进度追踪
[HideInInspector] public int currentKills = 0;
[HideInInspector] public bool tacticsUnlocked = false;
[HideInInspector] public bool loreUnlocked = false;
}
public class LoadingScreenNarrative : MonoBehaviour
{
private string[] loadingTips = new string[]
{
// 游戏提示(70%)
"圣光塔可以减速附近的敌人",
"诅咒虽然危险,但奖励丰厚",
// Lore 提示(30%)
"\"暗夜降临前,王国曾有七座圣塔。\" - 古老预言",
"传说中,第一位吸血鬼是堕落的大主教",
};
void OnLoadingStart()
{
// 70% 概率显示提示,30% 显示 Lore
bool showLore = Random.value < 0.3f;
if (showLore)
{
var loreTips = loadingTips.Where(t => t.Contains("\"")).ToArray();
loadingText.text = loreTips[Random.Range(0, loreTips.Length)];
}
else
{
var gameTips = loadingTips.Where(t => !t.Contains("\"")).ToArray();
loadingText.text = gameTips[Random.Range(0, gameTips.Length)];
}
}
}
public class DeathScreenNarrative : MonoBehaviour
{
void OnPlayerDeath(DeathContext context)
{
// 根据死亡原因显示不同文本
string narrativeText = context.killerType switch
{
EnemyType.Boss => "你倒在了 Boss 的力量之下...",
EnemyType.Elite => "精英敌人击碎了你的防线",
EnemyType.Swarm => "数量终究压倒了一切",
_ => "暗夜吞噬了又一位猎人"
};
deathQuote.text = narrativeText;
// 连续死亡 ≥ 3 次,显示鼓励文本
if (context.consecutiveDeaths >= 3)
{
encouragementText.text = "\"失败是通往胜利的必经之路。\" - 导师寄语";
}
}
}
Hades 是肉鸽类叙事设计的巅峰,解决了”重复游玩 = 重复剧情”的难题。
叙事系统架构:
第 1 次 Run:
- 扎格雷乌斯: "我要逃出冥界!"
- 冥王: "你逃不掉的,孩子。"
第 10 次 Run:
- 扎格雷乌斯: "又失败了...但我学会了新技能。"
- 冥王: "你的执着令我...意外。"
第 50 次 Run:
- 扎格雷乌斯: "父亲,告诉我真相!"
- 冥王: "...好吧,是时候了。"(剧情转折)
第 100 次 Run:
- 新角色加入对话
- 已有角色关系发生变化
设计亮点:
Vampirefall 借鉴:
Slay the Spire 几乎没有显性剧情,但通过碎片化文本构建了完整世界观。
叙事载体:
| 元素 | 叙事方式 | 例子 |
|---|---|---|
| 卡牌名称 | 暗示技能来源 | “献祭” → 邪教仪式 |
| 卡牌描述 | 风味文本 | “疼痛是暂时的,力量是永恒的” |
| 敌人名称 | 暗示生态 | “培养者” → 他们在培养怪物 |
| 事件文本 | 环境叙事 | “你发现了一座古老的神龛…” |
| 遗物描述 | 历史碎片 | “曾属于第一位攀登者” |
设计哲学:
“玩家会自己脑补完整的故事。”
最佳实践:
坏的风味文本: "这张卡增加 3 点力量"(纯机制描述)
好的风味文本: "\"力量源于绝望。\" - 无名战士"(暗示背景)
坏的遗物名: "+2 力量戒指"
好的遗物名: "堕落勇士的遗骸"(暗示前代冒险者)
Vampirefall 借鉴:
Dead Cells 用纯视觉叙事讲述了一个病毒爆发与王国覆灭的故事。
环境叙事技巧:
收集者: "你又死了?有趣...你似乎记不得之前的事。"
(暗示玩家是不死生物)
物品 1: "国王的命令:封锁岛屿。"
物品 2: "炼金术士的笔记:实验失败了。"
物品 3: "王后的信:原谅我,我的爱。"
(拼凑出完整剧情)
设计公式:
完整故事 = Σ(碎片 1 + 碎片 2 + ... + 碎片 N)
每个碎片:
- 独立时:有趣但不完整
- 组合后:拼凑出完整真相
Vampirefall 借鉴:
Vampire Survivors 证明了:即使叙事极简,包装仍然重要。
叙事元素清单:
✅ 开场字幕:简单背景设定(30 秒)
✅ 角色名称:暗示身份("Imelda Belpaese" = 意大利裔)
✅ 武器名称:风格化("圣水" "大蒜" = 吸血鬼克星)
✅ 地图名称:营造氛围("绿色阴影" "不朽者的坟墓")
❌ 无对话系统
❌ 无剧情推进
❌ 无过场动画
设计哲学:
“叙事不能干扰核心玩法,但可以增强主题氛围。”
成功要素:
Vampirefall 借鉴:
Environmental Storytelling
Henry Jenkins (MIT)
论文 PDF
Narrative Design in Roguelikes
GDC 2021 - Greg Kasavin (Supergiant Games)
YouTube 链接
The Narrative Potential of Replay
Extra Credits
YouTube 视频
[GDC 2021] Writing Hades
演讲者: Greg Kasavin
GDC Vault
[GDC 2018] Narrative Design in Slay the Spire
演讲者: Anthony Giovannetti
YouTube 链接
[GDC 2017] Environmental Storytelling in The Last of Us
演讲者: Richard Cambier (Naughty Dog)
GDC Vault
Writing for Roguelikes - Gamasutra
文章链接
The Power of Flavor Text
Medium 分析
Narrative Systems in Games
Game Developer 深度文章
《游戏叙事设计》 (Interactive Storytelling for Video Games)
作者: Josiah Lebowitz, Chris Klug
《游戏写作手册》 (The Game Narrative Toolbox)
作者: Tobias Heussner 等
《故事》 (Story)
作者: Robert McKee
(虽然不是游戏专著,但叙事原理通用)
最后更新: 2025-12-04
维护者: Vampirefall 设计团队