Skip to main content
摘要:本文档指导如何构建游戏地图以及控制刷怪节奏 (Pacing)。

1. 地图生成逻辑 (Map Generation)

本作不使用完全随机的迷宫,而采用 “模块化拼图” (Modular Tiles) 系统,兼顾战术深度与随机性。

1.1 核心结构

  • 基地 (Hub): 地图中心,不可破坏,玩家必须守护的核心。
  • 主路 (Lanes): 连接刷怪点 (Spawners) 和基地的主要路径。
  • 空地 (Plots): 允许玩家建造防御塔的区域。
    • 高地 (High Ground): 放置在此处的塔获得 +20% 射程。
    • 能量节点 (Power Nodes): 放置在此处的塔攻速 +30%,但造价翻倍。

1.2 地形阻挡与迷宫 (Mazing)

  • 地图初始是开放的。
  • 玩家可以通过建造“墙壁”或“阻挡塔”来改变怪物的寻路。
  • 限制: 系统必须保证至少有一条从刷怪点到基地的通路(不能完全堵死)。如果完全堵死,怪物进入“狂暴模式”,攻击力翻倍并开始拆墙。

2. 波次节奏控制 (Wave Pacing)

一局游戏标准时长为 20 分钟,分为若干波次。

2.1 强度曲线 (Intensity Curve)

  • 采用 正弦波 模式:
    • Build Up: 少量杂兵,给玩家送钱造塔。
    • Peak: 高密度刷怪,混合精英。
    • Climax: Boss 战或超高压波次。
    • Rest: 只有零星小怪,给玩家整理装备、升级塔的时间。

2.2 刷怪配置 (Spawn Patterns)

  • 线性流 (Stream): 连续不断地刷单一兵种。测试单体输出。
  • 爆发流 (Burst): 瞬间刷出一大群低血量怪。测试 AoE 能力。
  • 钳形攻势 (Pincer): 两个相反方向的刷怪点同时激活。强迫玩家分兵或构建全向防御。

3. 动态难度调整 (Dynamic Difficulty - Director)

参考《求生之路》的 AI Director。
  • 监测指标: 玩家血量、塔的损毁率、DPS 统计。
  • 调整:
    • 如果玩家过于轻松(满血,塔未受损),下一波提前刷新,或者增加精英怪数量。
    • 如果玩家濒死,下一波刷怪间隔延长,或掉落回复球。

4. 地图事件 (Map Events)

为了打破枯燥,随机触发地图事件。
  • 血月 (Blood Moon): 所有怪物攻速 +30%,但掉落稀有度提升。
  • 虚空裂隙 (Void Rift): 地图随机位置开启传送门,刷出偷袭基地的怪物。玩家必须去关闭它。
  • 流浪商队 (Wandering Trader): 一个无敌的 NPC 经过地图,玩家可以购买急需的消耗品。

5. 敌人 AI 寻路系统 (Enemy Pathfinding)

5.1 寻路算法选择

Unity NavMesh vs A* vs Flow Field
算法适用场景优点缺点
Unity NavMesh地形复杂,怪物数量 < 100自动烘焙,支持动态障碍移动端性能差
A*网格地图,中等数量敌人精确路径,易于理解大量敌人时 CPU 消耗高
Flow Field大量敌人 (>500) 向同一目标移动极高性能,适合塔防实现复杂,不支持个体差异
推荐方案: 使用 Flow Field 作为主要算法。

5.2 Flow Field 原理

核心思想: 预先计算地图上每个格子的”流向”,所有怪物只需查表移动。
// 1. 从目标点(基地)开始,反向 BFS
public void GenerateFlowField(Vector2Int goal)
{
    Queue<Vector2Int> queue = new Queue<Vector2Int>();
    queue.Enqueue(goal);
    distanceField[goal.x, goal.y] = 0;

    while (queue.Count > 0)
    {
        Vector2Int current = queue.Dequeue();
        foreach (Vector2Int neighbor in GetNeighbors(current))
        {
            if (IsWalkable(neighbor))
            {
                int newDist = distanceField[current.x, current.y] + 1;
                if (newDist < distanceField[neighbor.x, neighbor.y])
                {
                    distanceField[neighbor.x, neighbor.y] = newDist;
                    queue.Enqueue(neighbor);
                }
            }
        }
    }

    // 2. 根据距离场生成流向
    GenerateVectorField();
}

// 3. 怪物移动:直接查表
public Vector3 GetFlowDirection(Vector3 position)
{
    Vector2Int gridPos = WorldToGrid(position);
    return flowField[gridPos.x, gridPos.y];
}
性能优化:
  • 只在地图变化时(玩家建塔/拆塔)重新计算。
  • 使用 Job System + Burst Compiler 并行化计算。

5.3 动态阻挡处理

问题: 玩家建塔后,怪物的路径可能被堵死。 解决方案:
public bool CanPlaceTower(Vector2Int position)
{
    // 临时标记这个格子为阻挡
    SetBlocked(position, true);

    // 重新计算 Flow Field
    GenerateFlowField(basePosition);

    // 检查所有刷怪点是否还能到达基地
    foreach (Vector2Int spawner in spawnerPositions)
    {
        if (distanceField[spawner.x, spawner.y] == int.MaxValue)
        {
            // 无法到达,不允许建塔
            SetBlocked(position, false);
            return false;
        }
    }

    return true;
}
[!WARNING] > 狂暴模式触发条件 如果玩家通过某种方式(如 Bug)完全堵死路径,怪物会进入狂暴模式
  • 攻击力 +100%
  • 移速 +50%
  • 优先攻击阻挡物(塔或墙)
  • 持续破坏直到开辟出新路径

6. 波次编辑器详细配置 (Wave Editor)

6.1 波次类型 (Wave Type)

定义不同的波次模板:
{
  "wave_types": {
    "Standard": {
      "enemy_count_range": [20, 50],
      "spawn_interval": 1.0,
      "spawner_count": 1
    },
    "Burst": {
      "enemy_count_range": [100, 200],
      "spawn_interval": 0.1,
      "spawner_count": 1,
      "description": "瞬间刷出大量弱怪"
    },
    "Pincer": {
      "enemy_count_range": [30, 60],
      "spawn_interval": 0.5,
      "spawner_count": 2,
      "spawners": ["North", "South"],
      "description": "双向夹击"
    },
    "Elite": {
      "enemy_count_range": [5, 10],
      "spawn_interval": 3.0,
      "elite_ratio": 1.0,
      "description": "所有怪都是精英"
    },
    "Boss": {
      "enemy_count_range": [1, 1],
      "spawn_interval": 0,
      "boss_id": "BossName"
    }
  }
}

6.2 强度曲线配置 (Intensity Curve)

使用函数曲线控制难度:
{
  "intensity_curve": {
    "type": "sine_wave",
    "parameters": {
      "amplitude": 1.5,
      "frequency": 0.2,
      "baseline": 1.0
    }
  }
}
对应的代码实现:
public float GetWaveIntensity(int waveNumber)
{
    float t = waveNumber * frequency;
    float intensity = baseline + amplitude * Mathf.Sin(t);
    return Mathf.Max(0.5f, intensity); // 最低 0.5x 难度
}

public int GetEnemyCount(int baseCount, int waveNumber)
{
    return Mathf.RoundToInt(baseCount * GetWaveIntensity(waveNumber));
}

7. 性能优化指南 (Performance Optimization)

7.1 对象池 (Object Pooling)

问题: 频繁生成/销毁敌人会导致 GC 卡顿。 解决方案:
public class EnemyPool : MonoBehaviour
{
    private Dictionary<string, Queue<Enemy>> pools = new Dictionary<string, Queue<Enemy>>();

    public Enemy Spawn(string enemyId, Vector3 position)
    {
        if (!pools.ContainsKey(enemyId))
            pools[enemyId] = new Queue<Enemy>();

        Enemy enemy;
        if (pools[enemyId].Count > 0)
        {
            enemy = pools[enemyId].Dequeue();
            enemy.transform.position = position;
            enemy.gameObject.SetActive(true);
        }
        else
        {
            enemy = Instantiate(GetEnemyPrefab(enemyId), position, Quaternion.identity);
        }

        enemy.OnDeath += () => Recycle(enemyId, enemy);
        return enemy;
    }

    private void Recycle(string enemyId, Enemy enemy)
    {
        enemy.gameObject.SetActive(false);
        pools[enemyId].Enqueue(enemy);
    }
}

7.2 批量渲染 (GPU Instancing)

启用 GPU Instancing:
  • 所有同类敌人使用同一个 Material
  • 在 Shader 中勾选 Enable GPU Instancing
[!TIP] > 移动端优化关键指标
  • Draw Calls < 100
  • Batches < 50
  • 总三角面数 < 500K
  • 同屏敌人 < 200

8. 调试工具与技巧 (Debugging Tools)

8.1 关卡测试控制台

运行时调试工具:
public class LevelDebugger : MonoBehaviour
{
    private void OnGUI()
    {
        GUILayout.BeginArea(new Rect(10, 10, 300, 500));

        GUILayout.Label($"Current Wave: {WaveManager.Instance.CurrentWave}");
        GUILayout.Label($"Enemies Alive: {EnemyManager.Instance.AliveCount}");

        if (GUILayout.Button("Skip to Wave +5"))
            WaveManager.Instance.SkipToWave(WaveManager.Instance.CurrentWave + 5);

        if (GUILayout.Button("Add 1000 Gold"))
            PlayerData.Gold += 1000;

        GUILayout.EndArea();
    }
}

8.2 寻路可视化

绘制 Flow Field:
private void OnDrawGizmos()
{
    if (!Application.isPlaying || flowField == null) return;

    for (int x = 0; x < gridWidth; x++)
    {
        for (int y = 0; y < gridHeight; y++)
        {
            Vector3 worldPos = GridToWorld(new Vector2Int(x, y));
            Vector3 flow = flowField[x, y];

            // 绘制箭头
            Gizmos.color = Color.yellow;
            Gizmos.DrawLine(worldPos, worldPos + flow * 0.5f);
        }
    }
}

9. 常见错误与解决方案 (Common Pitfalls)

9.1 错误:怪物卡在墙里

原因: 寻路网格精度不足,或者移速过快导致穿墙。 解决:
private void FixedUpdate()
{
    Vector3 desiredVelocity = GetFlowDirection(transform.position) * speed;
    rb.velocity = Vector3.Lerp(rb.velocity, desiredVelocity, 0.5f);

    // 检测穿墙
    if (Physics.Raycast(transform.position, rb.velocity.normalized, out hit, rb.velocity.magnitude * Time.fixedDeltaTime))
    {
        if (hit.collider.CompareTag("Wall"))
        {
            rb.velocity = Vector3.zero;
            RegeneratePathToGoal();
        }
    }
}

9.2 错误:动态难度系统过于敏感

解决: 使用移动平均平滑数据。
private Queue<float> recentPerformance = new Queue<float>();

public float GetAveragePerformance()
{
    return recentPerformance.Average();
}

public void AdjustDifficulty()
{
    float avg = GetAveragePerformance();
    if (avg > 0.8f)
        difficultyMultiplier += 0.1f;
    else if (avg < 0.3f)
        difficultyMultiplier -= 0.1f;

    difficultyMultiplier = Mathf.Clamp(difficultyMultiplier, 0.5f, 2.0f);
}
[!CAUTION] > 动态难度调整的副作用 过于激进的难度调整可能让玩家感觉”系统在针对我”。建议:
  • 只在玩家连续 3 波表现过好/过差时才调整
  • 调整幅度不超过 ±10%
  • 在 UI 中不要明确告知玩家难度已调整

10. 关卡 JSON 示例

{
  "level_id": "Lvl_Graveyard_01",
  "waves": [
    {
      "time_start": 0,
      "duration": 60,
      "spawners": ["North", "South"],
      "enemies": [
        { "id": "Zombie", "count": 50, "interval": 1.0 },
        { "id": "Skeleton_Archer", "count": 10, "interval": 5.0 }
      ]
    },
    {
      "time_start": 70,
      "type": "Rest",
      "duration": 30
    }
  ]
}

10.1 完整关卡配置示例

包含所有配置项的高级示例:
{
  "level_id": "Lvl_Graveyard_Hard",
  "level_name": "墓地围攻:困难模式",
  "recommended_player_level": 10,

  "map_config": {
    "grid_size": { "x": 50, "y": 50 },
    "spawners": [
      { "id": "North", "position": { "x": 25, "y": 0 } },
      { "id": "South", "position": { "x": 25, "y": 49 } },
      { "id": "East", "position": { "x": 49, "y": 25 } }
    ],
    "base_position": { "x": 25, "y": 25 },
    "special_zones": [
      {
        "type": "HighGround",
        "area": [
          { "x": 10, "y": 10 },
          { "x": 15, "y": 15 }
        ],
        "bonus": "+20% Range"
      },
      {
        "type": "PowerNode",
        "position": { "x": 30, "y": 30 },
        "bonus": "+30% AttackSpeed",
        "cost_multiplier": 2.0
      }
    ]
  },

  "waves": [
    {
      "wave_number": 1,
      "type": "Standard",
      "time_start": 0,
      "duration": 60,
      "spawners": ["North"],
      "enemies": [
        { "id": "Zombie", "count": 30, "interval": 1.5 },
        { "id": "Skeleton", "count": 10, "interval": 3.0 }
      ]
    },
    {
      "wave_number": 2,
      "type": "Burst",
      "time_start": 70,
      "duration": 20,
      "spawners": ["North", "South"],
      "enemies": [{ "id": "Bat_Swarm", "count": 100, "interval": 0.2 }],
      "warning_message": "蝙蝠群来袭!"
    },
    {
      "wave_number": 3,
      "type": "Rest",
      "time_start": 100,
      "duration": 30,
      "special_event": "WanderingTrader"
    },
    {
      "wave_number": 4,
      "type": "Elite",
      "time_start": 140,
      "duration": 90,
      "spawners": ["North", "South", "East"],
      "enemies": [
        { "id": "Armored_Ghoul", "count": 15, "interval": 5.0 },
        { "id": "Necromancer", "count": 3, "interval": 20.0 }
      ],
      "map_event": { "type": "BloodMoon", "duration": 90 }
    },
    {
      "wave_number": 5,
      "type": "Boss",
      "time_start": 240,
      "spawners": ["North"],
      "enemies": [{ "id": "Boss_Lich_King", "count": 1, "interval": 0 }],
      "music_override": "Music_Boss_Theme",
      "camera_mode": "Cinematic"
    }
  ],

  "difficulty_settings": {
    "base_health_multiplier": 1.5,
    "base_damage_multiplier": 1.3,
    "gold_drop_multiplier": 1.2,
    "dynamic_adjustment": {
      "enabled": true,
      "max_multiplier": 2.0,
      "min_multiplier": 0.7
    }
  },

  "rewards": {
    "first_clear": [
      { "type": "Gold", "amount": 5000 },
      { "type": "Item", "id": "Relic_Death_Knight_Helm" }
    ],
    "perfect_clear": [
      { "type": "Achievement", "id": "No_Damage_Graveyard" },
      { "type": "Title", "id": "Undead_Slayer" }
    ]
  }
}

本文档侧重于具体实现和配置。如需了解设计理论,请参阅:
[!NOTE] > 理论基础 查看 🗺️ 关卡设计理论:节奏、空间与引导 了解:
  • 空间结构理论(路径类型、扼守点)
  • 节奏控制理论(起承转合、心流通道)
  • 认知负荷理论(UI 设计原则)
  • 业界案例分析(Dark Souls、Hades)
其他相关文档:

🗺️ 关卡设计理论:节奏、空间与引导

核心理念: 优秀的关卡设计是无形的。它在玩家不知不觉中教会他们规则,引导他们去往正确的地方,并在他们即将厌倦时提供新的刺激。

1. 🏯 空间结构理论 (Spatial Structure)

在塔防与动作混合的游戏中,空间决定了策略。

1.1 路径类型 (Path Typology)

  • 单线型 (The Corridor): 怪物只有一条路。最简单,适合教学关。玩家只需把火力集中在一点。
  • 分岔型 (The Fork): 怪物分两路,最后汇合。强迫玩家分散火力或寻找交汇点(Kill Zone)。
  • 多入口型 (Multi-Spawn): 怪物从东南西北涌入,保护中心。这是 Vampire Survivors 的典型结构,考验玩家的 AOE 能力和走位。
  • 循环型 (The Loop): 怪物会绕圈(如围绕核心),给玩家更多的输出时间,但一旦漏怪就很难追回。

1.2 扼守点与杀戮区 (Choke Points & Kill Zones)

  • 定义: 地图中地形狭窄,强迫怪物聚集成一团的区域。
  • 设计原则:
    • 黄金位: 扼守点旁边必须有 1-2 个“高价值”造塔位。
    • 陷阱: 扼守点是放置减速塔、地雷的最佳位置。
    • 玩家引导: 通过地形(石头、树木)自然地将怪物“挤”到扼守点,而不是用空气墙。

1.3 视线与遮挡 (Line of Sight / LoS)

  • 应用: 在 3D 塔防中,视线遮挡是高级策略。
  • 掩体: 在路径中间放置一块巨石。
    • : 直射塔(机枪)打不到石头后面的怪。
    • : 远程怪会躲在石头后面攻击塔。
    • 对策: 玩家必须建造抛射塔(迫击炮)或亲自绕后解决。

2. 📈 节奏控制理论 (Pacing & Flow)

关卡不是静态的,它是时间的艺术。

2.1 起承转合 (Kishōtenketsu) - 任天堂关卡法

  • 起 (Introduction): 安全环境下引入新机制。
    • 例子: 出现一种带护盾的怪,单独一只,慢慢走,玩家发现普攻打不动,直到造了激光塔。
  • 承 (Development): 稍微增加难度。
    • 例子: 护盾怪成群出现,混杂在普通怪里。
  • 转 (Twist): 机制反转或结合。
    • 例子: 护盾怪学会了冲锋,或者配合加血怪一起出现。
  • 合 (Conclusion): 终极考验 (Mastery)。
    • 例子: BOSS 战,BOSS 自带巨型护盾,还会召唤小护盾怪。

2.2 强度曲线 (Intensity Curve)

  • 锯齿状上升: 永远不要让难度呈直线增加。
    • Wave 1: 简单 (热身)
    • Wave 2: 中等
    • Wave 3: 困难 (压力测试)
    • Wave 4: 简单 (休息/奖励/整顿) -> 关键的低谷,给玩家喘息和花钱的时间。
    • Wave 5: 极难 (BOSS)

3. 🧭 引导与教学 (Guidance & Tutorial)

3.1 视觉引导 (Visual Language)

  • 光照: 把光打在重要的路口或目标点上。人眼本能趋光。
  • 路标: 地面上的车辙印、血迹、散落的金币,都能暗示“怪物从哪来”或“该往哪走”。
  • 地标 (Landmarks): 远处的巨大雕像或高塔,帮助玩家定位方向(在开放地图中尤为重要)。

3.2 既然是塔防… (TD Specifics)

  • 预警线: 在波次开始前,用红线画出怪物即将行走的路径。
    • 重要性: 既然策略重于反应,就必须给玩家完全的信息。隐藏路径不仅不难,反而令人沮丧。
  • 建筑网格: 在玩家进入建造模式时,清晰地显示网格和不可建造区域 (红/绿格)。

4. 🛠️ 关卡设计检查清单 (Checklist)

  1. 策略多样性: 这张图是否只有一种最优解?如果是,重做。
  2. 防守点: 是否有明显的“最佳防守位”?是否有给远程英雄发挥的高台?
  3. 防卡死: 所有的出生点到终点是否保证连通?(防止玩家用塔堵死路)。
  4. 时长: 一局是否控制在 15-20 分钟?(移动端黄金时长)。

5. 案例分析:Dust 2 (CS:GO) vs Kingdom Rush

  • Dust 2: 经典的“田”字型结构。中门 (Mid) 是核心争夺点,连接 A/B 两点。塔防也可以借鉴这种多线互通结构,让玩家在两条路之间疲于奔命,必须用传送门或高机动英雄救场。
  • Kingdom Rush: 每一关都引入一个新塔或新怪。利用地形(如从河里突然钻出的怪)打破玩家的既定防线,强迫重建。

6. 🌊 心流理论在关卡设计中的应用 (Flow Theory)

6.1 心流通道 (Flow Channel)

心流 (Flow) 是心理学家 Mihaly Csikszentmihalyi 提出的概念,指人在完全沉浸于某项活动时的最佳体验状态。 在关卡设计中的应用:
  • 玩家技能曲线: 随着游戏进程,玩家会掌握新塔、新技能。
  • 挑战曲线: 关卡难度必须同步增长,保持在心流通道中。
  • 动态调整: 如果玩家明显在某一关卡重复失败,说明已进入”焦虑区”,需要降低难度或提供更多提示。

6.2 挑战类型的多样性

单一类型的挑战会快速消耗心流。必须混合:
  • 反应挑战: 快速的刷怪波次,测试 APM (Actions Per Minute)。
  • 策略挑战: 资源有限,需要规划塔的位置和升级顺序。
  • 知识挑战: 某种怪只能被特定塔克制,玩家必须”读图鉴”。
  • 适应挑战: 地图事件突然改变规则(如”所有塔攻击力减半”),玩家需要临场应变。

7. 🧠 认知负荷理论 (Cognitive Load Theory)

7.1 三种认知负荷

认知负荷理论 (CLT) 由 John Sweller 提出,区分了三种类型的负荷:
类型定义示例 (塔防)设计原则
内在负荷 (Intrinsic)任务本身的复杂度”这个塔打物理伤害还是魔法伤害?“不可避免,但可以通过教程分阶段引入
外在负荷 (Extraneous)糟糕的界面设计造成的额外负担”我不知道怎么旋转塔的朝向”必须消除!清晰的 UI 和反馈
相关负荷 (Germane)用于构建技能和理解的有效思考”我发现这个塔放在拐角效果更好”应该鼓励!通过引导式谜题培养

7.2 减少外在负荷的实战技巧

[!TIP] > 信息分层显示
  • 默认只显示关键信息(如塔的攻击力、射程)。
  • 高级信息(如暴击率、穿甲值)放在”详细面板”中,点击才显示。
[!TIP] > 色彩编码
  • 物理伤害 = 橙色 🟠
  • 魔法伤害 = 蓝色 🔵
  • 真实伤害 = 紫色 🟣
  • 玩家在战斗中一眼就能识别塔的类型。
[!TIP] > 预览系统
  • 在放置塔之前,显示射程圈模拟 DPS(对当前波次的怪)。
  • 让玩家做出有信息支撑的决策,而不是盲猜。

8. 🎮 业界案例深度解析 (Case Studies)

8.1 案例 1: Dark Souls - 惩罚与学习的艺术

核心设计哲学: “Death is the Teacher” 关卡结构分析:
  • 捷径机制: 每个区域都有隐藏的捷径,连接篝火(存档点)和 BOSS 房。
    • 第一次: 玩家会走很长的路,遭遇大量敌人。
    • 第二次: 解锁捷径后,可以直接冲向 BOSS,减少消耗和沮丧感。
    • 设计启示: 尊重玩家的时间。失败惩罚应该是”失去进度”,而非”重复无意义的内容”。
在塔防中的应用:
  • 波次快进: 如果玩家在第 15 波失败,重新开始时可以选择”从第 10 波开始,但资源减半”。
  • 失败奖励: 即使失败,也给予少量货币或经验,让玩家感觉”没有白玩”。

8.2 案例 2: Hades - Roguelike 的渐进式揭示

核心设计哲学: “Every Run Matters” 元进度系统:
  • 玩家每次失败后,可以用收集的资源永久强化角色。
  • 随着死亡次数增加,新对话、新剧情、新技能逐渐解锁。
  • 关键: 失败不是终点,而是体验剧情和成长的必经之路。
在塔防中的应用:
  • 遗物系统: 玩家在一局中获得的遗物(如”火塔伤害 +10%”),即使失败也能兑换成永久升级点。
  • 解锁式教学: 故意在前几局中限制玩家可建造的塔种类,强迫他们熟悉基础机制,再逐步开放高级塔。

8.3 案例 3: Slay the Spire - 卡牌与数值的平衡

关卡设计启示:
  • 分支路径: 玩家可以选择”安全路径”(小怪多,奖励稳定)或”危险路径”(精英怪,奖励丰厚)。
  • 在塔防中: 地图编辑器允许设计双线路径,玩家可以选择防守哪一条:
    • 路径 A: 怪物数量多但弱,资源掉落少。
    • 路径 B: 精英怪少但强,资源掉落丰厚。

9. 🧪 关卡测试方法论 (Playtesting \u0026 Iteration)

9.1 数据驱动的测试 (Data-Driven Testing)

记录关键指标:
  • 死亡热点图 (Death Heatmap): 玩家在哪一波、哪个位置最容易失败?
  • 塔的使用率: 如果某种塔从不被建造,说明它太弱或太贵。
  • 平均通关时长: 如果 90% 玩家在 5 分钟内通关,说明太简单。
工具推荐:
// Unity Analytics 示例
Analytics.CustomEvent("WaveFailed", new Dictionary<string, object>
{
    { "wave_number", currentWave },
    { "player_gold", playerGold },
    { "towers_built", towerCount }
});

9.2 定性测试 (Qualitative Testing)

观察新手玩家 (最重要!):
  • 不要给任何提示,只是观察。
  • 记录他们在哪里卡住、在哪里困惑
  • 如果新手不理解,那就是设计问题,不是玩家问题。
访谈问题:
  1. “你觉得哪一波最难?为什么?”
  2. “有没有某个塔让你觉得’完全没用’?”
  3. “如果可以改一个东西,你会改什么?“

9.3 迭代循环 (Iteration Loop)

[!IMPORTANT] > 关卡设计的黄金法则: 一个关卡必须经过至少 3 轮内部测试和至少 10 名外部玩家的试玩,才能视为”完成”。

📚 扩展阅读与灵感来源 (References)

🏯 关卡设计圣经

🛠️ 塔防特化

🧘 心流理论

🎓 认知科学

  • Cognitive Load Theory (John Sweller)
    • 详细解释内在/外在/相关负荷的区别及其在教学设计中的应用。
  • Don’t Make Me Think (Steve Krug)
    • 虽然是 UI/UX 书籍,但其”减少认知负荷”的原则完全适用于关卡设计。

本文档侧重于理论与原则。如需了解具体实现,请参阅:
[!NOTE] > 实战指南 查看 🗺️ 关卡与波次设计指南 了解:
  • 地图生成逻辑实现
  • 波次 JSON 配置
  • 动态难度调整系统
  • 地图事件触发机制
其他相关文档: