下载 App

一篇帖子搞定序列帧动画:从素材整理到角色、皮肤、怪物系统

精华04/18310 浏览开发交流
做 RPG、塔防、动作游戏,绕不开序列帧动画。角色走路、怪物攻击、技能特效,底层都是一帧一帧的图片快速切换。
这篇帖子从素材规范到代码实现,完整过一遍,不管你用什么引擎,思路都是通用的。欢迎留言补充。
horizontal linehorizontal line

一、先搞清楚你的素材类型

拿到素材包,先判断它是哪种结构,后续处理方式完全不同。

类型 A:精灵图集(Sprite Sheet)

所有帧拼在一张大图上,需要按坐标裁切。
┌──────────────────────────────┐
│ [帧0] [帧1] [帧2] [帧3] ... │  ← idle 动作
│ [帧0] [帧1] [帧2] [帧3] ... │  ← walk 动作
│ [帧0] [帧1] [帧2] [帧3] ... │  ← attack 动作
└──────────────────────────────┘
优点:单文件,加载快;缺点:需要记录每帧的坐标和尺寸(通常配套一个 .json 或 .xml 描述文件)。

类型 B:平铺帧序列(Flat Frame Sequence)

每帧是单独的图片文件,按编号命名。
walk_00.png  walk_01.png  walk_02.png  ...
优点:直观,方便单帧替换;缺点:文件数量多,加载时 IO 次数多。

类型 C:带方向的帧序列(带方向前缀)

在平铺基础上加方向维度,常见于等距视角游戏。
d0_walk_00.png  ← 方向0(S)walk 第0帧
d4_walk_00.png  ← 方向4(N)walk 第0帧
d6_walk_00.png  ← 方向6(E)walk 第0帧
或者更隐式的:所有帧平铺成一个序列,方向按固定间隔排列(比如每隔 10 帧换一个方向)。
拿到素材第一件事:确认是哪种类型,搞清楚方向和动作的组织方式,再动代码。
horizontal linehorizontal line

二、素材规范:和美术/外购素材对齐

2.1 方向定义

等距视角常用 8 方向,俯视角常用 4 方向。方向的编号没有统一标准,常见的有两种:
方案一:从北顺时针(Unity/Unreal 常见)
N(0)
  NW(7)   NE(1)
W(6)         E(2)
  SW(5)   SE(3)
       S(4)
方案二:从东逆时针(数学角度约定)
N
  NW       NE
W               E(0°)
  SW       SE
       S
  关键:收到外购素材时,必须问清楚或自己测试哪个编号对应哪个方向。
  不要假设,美术的"南"和你代码里的"南"很可能不是同一个方向。

2.2 建议的文件命名规范

```
{角色ID}{动作}{方向}_{帧编号}.png
示例:
herowalkd000.png
hero
walkd001.png
heroattackd200.png
boss
idled600.png
```
或者用目录区分:
assets/
  characters/
    hero/
      idle/  d0_00.png  d0_01.png  d4_00.png ...
      walk/  d0_00.png  d0_01.png  ...
      attack/ ...
    enemy_elite/
      ...
规范的命名让代码用循环批量加载,省去大量硬编码。
horizontal linehorizontal line

三、动画系统设计

3.1 最小数据结构

每套动画(AnimClip)需要记录:
lua
{
    frames = {"d0_walk_00", "d0_walk_01", "d0_walk_02"},  -- 帧列表
    fps = 8,          -- 播放速率
    loop = true,      -- 是否循环
    faceRight = true, -- 该方向的帧是否朝右
}
注册表(Registry)把所有角色的所有方向、所有动作都预先索引好:
lua
REGISTRY["hero_walk_d0"] = { frames = {...}, fps = 8, loop = true }
REGISTRY["hero_walk_d4"] = { frames = {...}, fps = 8, loop = true }
-- ...

3.2 方向扇区计算

拿到移动向量 (dx, dy)
之后,计算角度,映射到最近的方向扇区:
lua
-- 屏幕坐标:X 右为正,Y 下为正
local function getDirectionSector(dx, dy)
    if math.abs(dx) < 0.01 and math.abs(dy) < 0.01 then
        return nil  -- 静止,保持当前方向
    end
    local angle = math.atan(dy, dx) * (180 / math.pi)
    if angle < 0 then angle = angle + 360 end
    -- 每个扇区 45°,加 22.5° 是为了让边界对齐方向中心
    local sector = math.floor((angle + 22.5) / 45) % 8
    return sector
end
然后用映射表把 sector 转成素材里的方向编号:
lua
-- 按你的素材实际标注填写,不要猜
local SECTOR_TO_DIR = {
    [0] = 6,  -- 向右(E) → 素材 dir6
    [1] = 7,  -- 右下(SE) → 素材 dir7
    [2] = 0,  -- 向下(S) → 素材 dir0
    [3] = 1,  -- 左下(SW) → 素材 dir1
    [4] = 2,  -- 向左(W) → 素材 dir2
    [5] = 3,  -- 左上(NW) → 素材 dir3
    [6] = 4,  -- 向上(N) → 素材 dir4
    [7] = 5,  -- 右上(NE) → 素材 dir5
}
把映射集中放在这一张表里,发现方向对不上只改这里,不用到处找代码。

3.3 帧推进逻辑

```lua
function updateAnimation(anim, dt)
    anim.timer = anim.timer + dt
    local frameDuration = 1.0 / anim.clip.fps
while anim.timer >= frameDuration do
    anim.timer = anim.timer - frameDuration
    anim.frameIndex = anim.frameIndex + 1
    if anim.frameIndex > #anim.clip.frames then
        if anim.clip.loop then
            anim.frameIndex = 1
        else
            anim.frameIndex = #anim.clip.frames
            anim.finished = true
        end
    end
end
return anim.clip.frames[anim.frameIndex]
end
```
horizontal linehorizontal line

四、镜像复用 vs 原生帧

什么时候可以用镜像?

1、角色完全左右对称(圆形小球、无武器的简单怪物)
2、素材制作量有限,预算不够做全 8 方向

什么时候不该用镜像?

1、等距视角角色(阴影、肩宽、武器握法都是不对称的)
2、角色身上有文字或图案
3、用了高质量外购素材,原生帧都有,没必要用镜像降质量

先确认素材完整性,再决定方案

收到素材包之后,做一个简单验算:
```
总帧数 ÷ 动作数 ÷ 每个动作平均帧数 = 方向数
例:360 帧 ÷ 3 个动作 ÷ 约 10 帧/动作 ≈ 12(异常,重新算)
    360 帧 ÷ 3 个动作 ÷ 15 帧/方向 = 8(8 方向,完整!)
```
如果方向数能整除 8,基本就是完整 8 方向,不需要镜像。
horizontal linehorizontal line

五、皮肤系统设计

皮肤的本质是:同一套动画逻辑,换一套帧图

方案一:注册表替换

每套皮肤预先注册一套 REGISTRY,切换皮肤时替换使用的注册表。
```lua
-- 默认皮肤
SKINS["default"]["herowalkd0"] = { frames = {"herowalkd0_00", ...} }
-- 黄金皮肤
SKINS["gold"]["herowalkd0"]    = { frames = {"herogoldwalkd000", ...} }
-- 切换皮肤
function setSkin(character, skinName)
    character.registry = SKINS[skinName]
end
```

方案二:纹理替换(只换图,不换帧序列)

适合帧数完全一致的皮肤(同一套骨架,换贴图颜色/材质):
lua
-- 加载不同皮肤纹理
character.texture = loadTexture("skins/" .. skinName .. "/walk_sheet.png")
-- 帧坐标不变,只换纹理引用

方案三:染色/调色(Shader 方案)

适合颜色变体皮肤:
lua
-- 用颜色矩阵调整色相,不需要多份素材
character.colorMatrix = HUE_ROTATE(120)  -- 红→绿
  建议先用方案一,简单直接,出问题好排查。方案三是进阶优化,先把游戏做出来再考虑。
horizontal linehorizontal line

六、常见坑速查

| 现象 | 最可能的原因 | 排查方法 |
|------|------------|---------|
| 所有方向都走背面 | 翻转逻辑 bug(falsy 值穿透) | 逐个 print 翻转值,检查分支是否走对 |
| 某几个方向走背面 | 方向映射表填错 | 强制固定方向测试,逐个确认素材对应关系 |
| 方向对,但镜像方向别扭 | 用了镜像但素材其实有原生帧 | 检查素材完整性,补提取缺失方向 |
| 纵向 S/N 对调 | 素材方向标注与代码约定不一致 | 在映射表里交换 S/N 的值 |
| 动画播放速率忽快忽慢 | 帧推进没有用 dt 累积,而是每帧固定推进 | 用累积时间而不是帧计数控制帧切换 |
| 切换皮肤后动画乱帧 | 切换皮肤时没有重置帧计数器 | setSkin 时同时 reset frameIndex 和 timer |
horizontal linehorizontal line

七、总结

做好序列帧动画,核心就三件事:
1. 搞清楚素材结构:方向怎么排,动作怎么分,每个方向几帧
2. 映射表集中管理:方向扇区 → 素材编号的映射放在一个地方,发现问题只改一处
3. 皮肤和逻辑分离:动画逻辑不依赖具体图片路径,换皮肤只换数据
猜你想搜
taptap 制造素材类型
别再烧积分了!从每次 2000 到每次 50 的血泪经验截图
别再烧积分了!从每次 2000 到每次 50 的血泪经验
适用场景:所有在用 TapTap Code 开发游戏的小白 难度:★☆☆☆☆ 背景最近群里总有人"炫耀"一次操作花了几千积分,说实话这不是值得高兴的事——这是在告诉所有人你的开发方式有根本性问题。我也走过这条弯路,所以来说说怎么改。 积分消耗的本质是什么积分 = AI 处理的 token 数量 = 你发给 AI 的内容 + AI 回给你的内容所以烧积分的本质只有两种: 你让 AI 做了大量无效/重
精华
68 赞
21 回复
01:27
《大二暑假,我用AI做了一款属于自己的游戏》截图
《大二暑假,我用AI做了一款属于自己的游戏》
本人自制游戏现已加入taptap封闭测试(仅适配安卓机型)欢迎大家前来尝试(八月十号可以正式开始游玩) 如果有建议或者bug反馈可以加入qq群928501443 #发现好游戏 #游戏日常 #浅评一下 #今天游戏圈发生了啥
3 赞
03:06
为了不被斩杀,我只能做到这些了截图
为了不被斩杀,我只能做到这些了
之前一直申请不到计划3,之前说太花哨,后面说体量完成度不足,在我一番小作文下,编辑终于给了我解答,什么原生质感,玩家开局体验啥的。 本来计划2也够用,准备以后再优化了,结果计划2赠送的积分要砍半了,学生党实在消费不起,于是只能再冲一波计划3了 从周六中午到现在一天半时间,优化了一遍角色卡,战斗卡,还有抽卡界面,优化了新手教程,该说不说确实比之前要舒服些。 前半部分为新版,后半部分为旧版。 明天再次
37 赞
6 回复
如何提升你游戏中的UI美术水平截图
如何提升你游戏中的UI美术水平
一、请为你的游戏挑选一款合适的字体 很多开发者没有注意到其实UI界面中最重要的元素是字体,一款合适的字体能给整个游戏的界面感官带来蜕变。 请看案例 那么如何挑选适合自己的字体呢? 我总结出了一些小经验可供参考: 黑体:通用 宋体:古风、武侠、修仙 楷体:古风、武侠、修仙 圆体:卡通、动漫、Q版 科技:科幻、未来、电子 顺手分享一个免费可商用字体网站: 当然 如果你不知道自己的游戏适合什么风格
精华
123 赞
44 回复
开发心得-界面布局心得截图
开发心得-界面布局心得
大家好,我正在用 TapTap 制造制作一款2D 治愈林间徒步旅行游戏《徒步荒野》。 我分享一下我的开发心得,希望能有用,下面是一些界面布局的心得。 第一步:定版式、操作 先确定游戏是横版还是竖版、需要哪些操作按钮,敲定整体玩法思路。 我的玩法灵感参考《边境之旅》,主打散步看风景、沿途触发随机事件。 原版是 3D,考虑到自己是新手,选择2D 横版街机式来做,制作更简单、好上手。 第二步:敲定全局美
6 赞
3 回复
00:26
塔啦啦科研:三渲二(风格1)截图
塔啦啦科研:三渲二(风格1)
最近在研究像素风格的三渲二,一直想做小丑牌那种风格,但是塔啦啦一直做不出来,发现是有一部分的功能做不了,只能实现简单的材质制作和描边,因此,我从零直接搭建了一整套引擎基础。目前进度可以看视频。 @嗒啦啦 什么时候出shader 评论区随意提问 #TapTap制造 #TapTap制造社区 #TapTap制造
4 赞
5 回复
永恒虚空持续开发日记1——关于游戏中的新名词:场频截图
永恒虚空持续开发日记1——关于游戏中的新名词:场频
写在前边:首先感谢TapTap制造版主大大@汪崽 对于作品潜力的肯定,给与了我积分计划二的权限[表情_不好意思]。这边也在加紧开发改进各种功能中,期望尽快给大家带来成熟的版本。[表情_猫咪举手] 大家好,我是永恒虚空的制作人黑猫不详,大家叫我黑猫就好。从今天开始我将以后置开发日记的形式给大家分享我在TapTap制造中制作的游戏永恒虚空的开发过程,新人希望大家多多关照! 今天先给大家介绍我作品中最重
投票
3 赞
2D 等轴测视角:完整理论截图
2D 等轴测视角:完整理论
2D 等轴测视角:完整理论 一、视角的本质 什么是等轴测 人站在高处斜着往下看地面,地面上的方格子不再是正方形,而变成了菱形。这就是等轴测的视觉本质。 俯视(正上方看下去): 等轴测(斜上方看下去): ┌──┬──┬──┐ ◇ ├──┼──┼──┤ ◇ ◇ ├──┼──┼──┤ ◇ ◇ ◇ └──┴──┴──┘ ◇ ◇ ◇ 正方形网格经过旋转 + 压缩,变成了菱形网格。 为什么是 2:1
6 赞
「游戏上新」秦王的游戏截图
「游戏上新」秦王的游戏
你是秦王嬴政身边的廷臣。 方士徐福献上一匣【帝王卡牌】,四张凶牌封死命运: 屠戮|淫欲|奢华|征伐 七日死限,必须一一折断卡牌对应的欲望任务。 办不成? 秦王殿上长剑出鞘,君臣性命,顷刻倾覆。 ⚔游戏核心玩法 ▪回合卡牌策略,抉择牵动秦廷朝堂势力 ▪朝堂派系博弈:王权、法家、军功贵族、方士暗流角力 ▪多重结局:功成辅秦王一统,或是任务失败血染咸阳宫 ▪随机事件触发,每一局嬴政的猜忌程度截然
4 赞
2 回复
【Tap make 塔拉拉之立项干货】萌新看过来!截图
【Tap make 塔拉拉之立项干货】萌新看过来!
题外话:本人也是tap make 使用者之一。塔啦啦忠实信徒、天哥忠实拥护者、八年游戏策划经验的低级策划。但是!我已经做出来一款5000+热度、且稳定可更新的框架、并且还在持续产出更多游戏内容的橘猫! 这几天正好在开新坑。我是3月初加入的tapmake大家庭。两周时间于3月25日将这个作品上架。当时的全凭感觉摸索。如今,自己也是一个有自己项目的小菜鸡了。今天,就来分享一下,如何高效的制作一款高大上
投票精华
68 赞
24 回复