创建一把武器分为以下步骤
在本文档中, 预制体=场景
武器预制体(场景)路径: res://prefab/weapon/
首先创建一个武器预制体, 右键res://prefab/weapon/WeaponTemplate.tscn
, 选择新建继承场景
创建完成后需要修改武器场景根节点名称
武器命名规范: Weapon+武器唯一Id
这个武器唯一Id
就是填在配置表中的id, 后面会讲到, 这里先确保唯一即可
以下是武器所有的节点
所有节点详细描述和注意事项:
texture
是空的, 游戏会自动根据AnimatedSprite
节点当前帧创建对应的阴影序列帧, 如果需要自定义阴影纹理, 例如一个阴影圈, 那么就可以手动给texture
属性赋值sprite_frames
数据, 需要自己创建shape
默认为空, 必须创建RectangleShape2D
(矩形)类型碰撞器floodlight
动画, 该动画为武器在地上时的高亮动画, 请不要编辑或者删除接下来就是创建武器脚本, 武器基类为Weapon
(路径:src/game/activity/weapon/Weapon.cs
), 并且Weapon
为抽象类, 因此我们需要创建一个子类并继承Weapon
我们创建一个MyGun.cs
, (如果不想自己实现武器逻辑, 可以直接跳过这一步, 并使用默认的枪类实现: Gun
, 路径: src/game/activity/weapon/gun/Gun.cs
)
using Godot; [Tool] //这个[Tool]必须添加, 否则将会在运行游戏时报错! public partial class MyGun : Weapon { protected override void OnFire() { //单次开火时调用的函数 } protected override void OnShoot(float fireRotation) { //发射子弹时调用的函数, 每发射一枚子弹调用一次, 如果做霰弹武器效果, 一次开火发射5枚子弹, 则该函数调用5次 //fireRotation – 开火时枪口旋转角度, 弧度制 } }
至于开火和发射子弹的具体逻辑, 这里不过多介绍, 请参照Gun
类
写完脚本后我们需要点击Godot
右上角的编译按钮
编译完成后就可以将MyGun
挂载到武器根节点下了(如果使用默认枪逻辑, 直接挂载Gun
脚本即可)
刚挂载脚本下面导出的属性都时空的, 不要害怕, 这一步不需要手动赋值
注意: 如果挂载脚本后没有出现以下属性, 说明脚本编译出错或者没有编译脚本
这里需要手动关闭场景再打开或者切换到其它页签再切回来, 导出的属性就会自动赋值, 最后记得ctrl+s
保存一下
到这里武器预制体创建完成
子弹预制体路径: res://prefab/bullet/
该文件夹目前包含三个子文件夹, 分别对应三种子弹类型
我们以最基础的normal
子弹为例
子弹不像武器有模板场景, 需要自由发挥, 但是我们可以直接复制其它子弹预制体, 然后改个名称即可
子弹命名方式和武器类似, 这里按照其它子弹照葫芦画瓢即可
以下是子弹所有的节点(我们是复制的Bullet0001.tscn
场景, 其它子弹场景可能会有所不同)
所有节点详细描述和注意事项:
IHurt.Hurt()
函数, 目标必须实现IHurt
接口Collision
稍微大一点, 大一点点即可CollisionShape2D
的区别, CollisionShape2D
是用于子弹击中目标检测的碰撞器, 而该节点为子弹运动的碰撞器, 这个是检测墙壁并反弹的, 这里不要搞混了到这里你就会发现, 武器和子弹都包含了 ShadowSprite, AnimatedSprite 和 Collision 这三个节点, 那是因为这三个节点是
ActivityObject
类提供的, 而武器和子弹都是ActivityObject
的子类, 因为游戏中基本上所有的实体物体都是ActivityObject
或者子类
接下来创建子弹脚本, 子弹没有硬性要求必须继承哪个父类, 相反, 它只需要实现IBullet
接口即可(路径: src/game/activity/bullet/normal/IBullet.cs
)
但是我们上面的操作复制的是Bullet0001.tscn
场景, 该场景为ActivityObject
场景, 所以我们的代码需要继承ActivityObject
子弹的实现非常复杂, 非常不建议自己从0开始实现, 直接抄作业使用现成的类Bullet
(路径: src/game/activity/bullet/normal/Bullet.cs
)
如果你非得头铁完全自己实现子弹逻辑, 那么有请, 已经起好了开头:
[Tool] public partial class MyBullet : ActivityObject, IBullet {
最后将脚本挂载到场景根节点即可
和武器一样, 这里会有几个引用需要复制
复制的流程也和武器一样, 要手动关闭场景再打开或者切换到其它页签再切回来, 自动赋值完成, 最后记得保存
子弹制作完成
Tips: laser(激光)
和explode(爆炸)
并不是ActivityObject
, 它们是由其它Godot原生节点实现的, 具体实现直接看它们挂载的脚本即可, 前提先把normal
类型的子弹玩明白
游戏中配置表路径: excel/
, 注意在godot工程根目录下
不过也有快捷按钮, 在godot编辑器中
先认识以下几张表
ActivityBase.xlsx: 负责注册ActivityObject
物体, 所有继承自ActivityObject
的场景都需要在这张表中填写配置信息, 这张表包含物体id
, 物体名称
, 物体品质
, 物体类型
, 物体物理材质
, 预制体路径
等基本数据
WeaponBase.xlsx: 负责记录武器属性数据, 比如弹容量
, 射速
, 散射值
, 连发属性
, 射出的子弹
, 音效
等
BulletBase.xlsx: 负责记录子弹的属性数据, 比如伤害
, 击退值
, 子弹速度
, 射程
, 穿透次数
, 反弹次数
等
ActivityBase.xlsx
表中武器: 填上id和名称, 物体类型为5, 再填上预制体路径和图标即可
子弹: 同样填上id和类型, 因为不需要显示在编辑器中, 名称可以不填, 再填上预制体路径即可
想偷懒可以直接复制其他行数据粘贴再改一改就行了
BulletBase.xlsx
表中子弹表字段不多, 描述基本上都介绍的非常详细了
这里提醒一下Prefab
字段, 当Type
字段值不同时, Prefab
填的内容也不相同
这张表Id建议和ActivityBase.xlsx
表中的Id
的最后的一串数字对应
WeaponBase.xlsx
表中武器表字段非常多, 武器各种属性区分的非常详细, 这里截图不会展示所有字段, 仅保留需要注意的字段
这张表需要注意的是一把武器需要填写两条武器数据, 这样做的目的就是为了让敌人拾起武器时不会像玩家一样可以一直连续开火, 那样太变态了, 为了限制敌人发射频率, 我们直接把武器属性抽成两份配置, 当玩家拾起武器时使用的是玩家配置, 当敌人拾起的时候就或读取属性较弱的ai配置了
这里玩家武器属性的Id建议和ActivityBase.xlsx
表中的Id
的最后的一串数字对应
Ai使用的武器属性有个潜规则, 就是玩家属性id+_ai
, 注意不要写错, 比如玩家使用的武器id为0001
, 那么Ai的武器id就是0001_ai
玩家使用的武器属性必须填写Activity
这一列
其他字段
Bullet: 射出的子弹, 填子弹ActivityBase.xlsx
表中的Id
Shell: 抛出的弹壳, 填子弹ActivityBase.xlsx
表中的Id
, 没有弹壳可以不填, 注意, 本文档没有介绍如何创建弹壳, 但本质流程和子弹相同, 并且弹壳没有额外逻辑, 所以制作弹壳比制作子弹简单, 这里自己摸索一下即可, 弹壳预制体路径: res://prefab/shell/
ShootSound: 射击播放的音效, 这个填Sound.xlsx
表Id
, 也就是音效表的数据Id, 本文档没有介绍音效表, 该表比较简单, 可以自己查看配置项
ShootSound
字段后面还有几个音效相关的属性, 例如换弹音效
, 上膛音效
等, 这里都不做赘述了
最后需要注意一下这个字段, 用于Ai武器的一些额外配置选项AiAttackAttr
, 值为AiAttackAttr.xlsx
表Id
AiAttackAttr.xlsx
表中有以下字段
如果以上所以配置都填写完成后, 那么就可以进行最后一步导出表数据到游戏中了
非常简单, 在Godot编辑器中点击工具
, 导出Excel表
按钮即可
但是注意, wps在打开excel表时会占进程, 导致导出表失败, 所以在导出表前一定要先关闭所有打开的excel表!
如果导表最终弹出以下弹窗说明导表成功
Tips: Godot工程中的导表攻击并不是编译好的二进制版本程序, 而是源代码, 第一次调用导表时会调用本机的dotnet
命令编译导表工具, 次步骤请确保安装了.net8
并dotnet
命令可以正常使用