Blender + Godot 4 制作 MOBA 防御塔:从低模、GLB 到碰撞与攻击范围

Blender + Godot 4 制作 MOBA 防御塔:从低模、GLB 到碰撞与攻击范围

OK,OK,大家好,欢迎大家来到大鹏 AI 教育,我是张大鹏。

防御塔看起来只是一个静态模型,放进游戏后却同时承担视觉地标、阻挡物、攻击者、目标选择器和范围提示等职责。问题往往不是"塔不会建模",而是 Blender 资产与 Godot 玩法逻辑没有划清边界。

本文以原创 MOBA 风格防御塔为案例,讲清一条可重复的 Blender → GLB → Godot 4 工作流。案例只借鉴品类结构,不使用《英雄联盟》的模型、贴图、地图或 UI。

先定义两端的职责

Blender 负责:

  • 网格轮廓、UV、材质槽和原点位置;
  • 可选的骨骼与动画;
  • 应用变换并输出稳定的 GLB。

Godot 负责:

  • 碰撞体、阵营、生命值与受击逻辑;
  • Area3D 攻击范围和目标筛选;
  • 射线遮挡、投射物、特效和音效;
  • 运行时材质覆盖与性能策略。

不要把玩法碰撞永久烘进美术源文件。塔的攻击半径是数值设计,不是网格设计。

Blender 阶段:先做可验证的低模

先用圆柱和立方体完成灰盒,确保底座、塔身、顶部三个层级清楚。建模时最重要的不是细节,而是以下约束:

  1. 原点放在底座中心,Z=0 对齐地面。
  2. 正面方向在团队内统一。
  3. 实际尺寸有参照物,不靠导入后随意缩放。
  4. 重复装饰尽量实例化,避免无意义地复制独立网格。

在导出前选择目标对象,执行 Ctrl + A,至少应用 Rotation 与 Scale。否则 Godot 中的碰撞、子节点变换和后续动画容易出现比例链问题。

为什么优先交付 GLB

.blend 直连适合个人快速迭代,但团队交付更推荐显式 GLB:

  • 单文件携带网格、材质和需要的纹理引用;
  • CI 和没有安装 Blender 的机器也能消费;
  • 导出选项可复核,边界比"自动读取整个工作源"更稳定;
  • Godot、Blender 升级时更容易定位变化来自哪一步。

导出时选择 glTF 2.0,启用"仅选中对象"。静态防御塔不需要摄像机、灯光、骨骼或动画,就不要一起打包。

Godot 阶段:把 GLB 当源场景

GLB 被导入后通常表现为一个不可直接随意修改的完整场景。正确做法是创建继承场景或包装场景,在外层添加玩法节点。

推荐场景树:

text 复制代码
DefenseTower (Node3D)
├── Visual (导入的 GLB 实例)
├── StaticBody3D
│   └── CollisionShape3D
├── AttackRange (Area3D)
│   └── CollisionShape3D
├── Muzzle (Marker3D)
├── FireTimer (Timer)
└── Health

这样重新导出同名 GLB 后,Visual 会更新,而 Godot 侧的碰撞、攻击范围和脚本仍然保留。

碰撞体要按玩法简化

静态塔通常不需要逐三角形精确碰撞。使用一个或两个圆柱、盒子组合即可:

  • 底座碰撞负责角色绕行;
  • 塔身可用较窄圆柱;
  • 装饰尖角不参与移动阻挡。

简化碰撞不仅更快,也让玩家移动更顺滑。视觉边缘过于复杂时,精确碰撞反而会制造"莫名其妙被卡住"的体验。

用 Area3D 表达攻击范围

gdscript 复制代码
class_name DefenseTower
extends Node3D

@export var team_id := 1
@export var damage := 40.0
@export var shots_per_second := 1.0

var candidates: Array[Node3D] = []
var current_target: Node3D

func _ready() -> void:
    $FireTimer.wait_time = 1.0 / shots_per_second
    $AttackRange.body_entered.connect(_on_body_entered)
    $AttackRange.body_exited.connect(_on_body_exited)
    $FireTimer.timeout.connect(_try_fire)
gdscript 复制代码
func _on_body_entered(body: Node3D) -> void:
    if body.is_in_group("combat_unit") and body.team_id != team_id:
        candidates.append(body)

func _on_body_exited(body: Node3D) -> void:
    candidates.erase(body)
    if current_target == body:
        current_target = null

Area3D 只维护候选集合,不要在每个物理帧遍历整张地图。开火时再做一次目标优先级和有效性检查。

目标选择要写成独立策略

不同玩法会优先选择:

  • 最先进入范围的单位;
  • 离塔最近的单位;
  • 沿兵线推进最远的单位;
  • 正在攻击友方英雄的单位。

把策略封装成函数,避免散落在攻击循环里:

gdscript 复制代码
func _select_target() -> Node3D:
    var valid := candidates.filter(
        func(unit): return is_instance_valid(unit) and not unit.is_dead
    )
    valid.sort_custom(
        func(a, b):
            return global_position.distance_squared_to(a.global_position) \
                < global_position.distance_squared_to(b.global_position)
    )
    return valid.front() if not valid.is_empty() else null

如果地图中存在墙体或高低差,再从 Muzzle 到目标发射 RayCast3D 或直接做物理空间查询,确认视线没有被阻挡。

资源更新时最容易踩的坑

  • 导入后直接改 GLB 子节点:重新导入可能覆盖修改。应使用继承/包装场景。
  • Blender 没应用缩放:碰撞体和子节点尺度难以判断。
  • 把所有材质做成唯一副本:失去批量更新能力。共享材质与实例覆盖要分清。
  • 用高精度网格碰撞:角色容易卡边,性能也更差。
  • 攻击范围跟着模型缩放:数值半径应在 Godot 中独立配置。

一次完整验收

  1. 在 Blender 改动塔顶轮廓并重新导出同名 GLB。
  2. Godot 自动重新导入,包装场景仍保留脚本和碰撞。
  3. 角色无法穿过底座,但不会被装饰尖角卡住。
  4. 敌方单位进入 Area3D 后加入候选,离开后立即移除。
  5. 友方单位不会成为目标。
  6. 射速、伤害和攻击半径可在 Inspector 调整。
  7. 删除目标节点不会留下失效引用或报错。

小结

一个可维护的防御塔不是"一个 GLB 加一段攻击脚本",而是清楚的资产契约:Blender 交付稳定视觉源,Godot 用包装场景承载碰撞和玩法,Area3D 管候选,独立策略管目标选择。

沿着这套边界继续扩展,就能加入血条、阵营材质、弹道、预警圈和拆塔阶段,而不必反复破坏美术资产。

参考资料

  • 《大鹏 Godot 4 游戏开发入门》第 3 章 3.7~3.9:GLB 导出、继承场景与高级导入
  • 《大鹏 Godot 4 游戏开发入门》第 6 章 6.4~6.6:3D 碰撞、Area3D 与物理查询
  • RuyiBlenderAI 与 RuyiGodotAI:分别承担 Blender 场景操作和 Godot 项目验证
相关推荐
Python私教3 天前
Godot 4 角色移动为什么要用 CharacterBody2D?从 Input Map 到碰撞滑动一次讲透
godot
Python私教3 天前
Godot 4 TileMapLayer 入门:从图集、碰撞到可玩的 2D 关卡
godot
Python私教3 天前
Godot图片怎么导入?PNG、压缩、Mipmap与Reimport一次讲清
游戏引擎·godot
Python私教3 天前
Blender模型导入Godot完整教程:GLB、BLEND与继承场景怎么选
运维·godot·blender
寒水馨3 天前
Linux下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_linux.x86_64.zip)
linux·游戏引擎·godot·游戏开发·2d游戏·3d游戏·godot engine
寒水馨3 天前
macOS下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_macos.universal.zip)
macos·3d·游戏引擎·godot·跨平台·游戏开发·2d
Python私教4 天前
Godot怎么下载和安装?零基础完成第一次启动
人工智能·游戏·godot