资讯动态

用Python一键生成2D角色帧动画:待机行走奔跑实战

发布时间:2026/10/18 13:37:09 来源:尧图企业网站定制
做 2D 游戏项目时最绕不开的一个环节就是角色动画。尤其是像素风、手绘风或者序列帧风格的独立游戏几乎全靠帧动画撑起角色的“灵魂”。待机时呼吸浮动行走时手脚交替奔跑时身体前倾——这些动作如果一张一张手动导出、再手动拖进引擎调参不仅枯燥还容易出错。本文围绕“帧动画一键生成”这条主线完整拆解一套用 Python 自动合成、自动预览、统一导出待机/行走/奔跑动作的实战方案。学会之后你不用再为帧动画的重复劳动头疼。文章适合刚接触 2D 动画的新手也适合正在做批量角色动画、想规范生产流程的开发者。1. 帧动画是什么为什么到今天依然重要1.1 帧动画的定义帧动画也叫序列帧动画本质上就是“连续播放一系列静态图片利用视觉暂留形成运动效果”。你可以把它理解成一本快速翻动的手翻书每一页是一张画面翻页速度足够快时画面里的人就会“动起来”。在游戏开发中每一张静态图片称为“一帧”。角色的一次走路动作可能由 6 到 8 帧组成一次攻击动作可能需要 10 到 15 帧。把这些帧按顺序循环播放就形成了完整的动作表现。帧动画和常见的 GIF 动图原理是一样的。区别在于游戏里的帧动画更强调帧率可控、循环无缝、透明背景、性能可控以及和游戏逻辑的交互。比如角色在跑步状态播放奔跑动画停止移动时切换回待机动画这需要通过代码或动画状态机来控制。1.2 帧动画与骨骼动画的区别很多新手会把帧动画和骨骼动画混为一谈。这里先做一个简单区分对比项帧动画骨骼动画数据组成多张完整图片帧一张角色贴图 骨骼层级 关键帧数据制作方式一帧一帧绘制或导入绑定骨骼后调整骨骼姿态文件体量帧数越多体量越大动画表现主要靠数据驱动贴图可复用风格适配非常适合手绘、像素、卡通风格适合写实、肢体动作复杂的 3D 或 2D 关节动画制作门槛较低美术功底要求高需要理解骨骼绑定和权重简单来说如果你做的是 Q 版休闲游戏、像素风 Roguelike、Live2D 那种偏手绘质感的 2D 项目帧动画通常是最直接、最可控的选择。如果角色需要大量换装、多部位组合骨骼动画会更省资源。两者不是谁替代谁的关系而是针对不同美术风格的方案取舍。1.3 帧动画的常见应用场景帧动画不只是游戏里用很多前端动态效果也能见到它的影子。常见场景包括游戏角色待机、走路、奔跑、跳跃、攻击、受伤等动作。UI 特效比如按钮点击特效、飘字、加载动画。角色表情变化比如对话时眨眼、张嘴、皱眉。技能特效比如剑气、火焰、雷电、爆炸。短视频和 H5 页面里的手绘动画。正因为应用场景广掌握一套“从素材到播放”的帧动画制作流程对独立开发者、前端工程师、游戏美术来说都是加分项。2. 准备工作环境与素材2.1 本教程使用的技术方案为了让教程可复现这里选用 Python 作为批量处理工具用 Pillow 库合成雪碧图Sprite Sheet用 Pygame 做动画预览。这个组合的好处是跨平台Windows、macOS、Linux 都能运行。不需要复杂的图形引擎知识只要会基础 Python 脚本就能用。可以很容易扩展成批量处理工具实现“一键生成”。如果项目最终要接入 Cocos、Unity 等引擎思路也是一样的先用脚本把序列帧打包成雪碧图再在引擎里创建 Animation Clip 或播放组件。2.2 安装 Python 与依赖库首先确保电脑里有 Python 3 环境。安装完成后打开终端或命令行执行下面命令pip install pillow pygamePillow 是 Python 的图像处理库负责读取 PNG、缩放图片、合成雪碧图。Pygame 是一个 2D 游戏开发库这里只用它的图像加载和窗口显示功能来预览动画。如果你的电脑网络环境下载慢可以加国内镜像源pip install pillow pygame -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后可以用下面命令验证python -c import PIL, pygame; print(PIL, PIL.__version__); print(pygame ok)能正常输出版本号说明环境已经就绪。版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。2.3 帧动画素材的组织方式制作帧动画前要先把素材整理好。这里推荐按“动作类型 序号”的方式组织文件assets/frames/ ├── idle_001.png ├── idle_002.png ├── idle_003.png ├── idle_004.png ├── walk_001.png ├── walk_002.png ├── walk_003.png ├── walk_004.png ├── walk_005.png ├── walk_006.png ├── run_001.png ├── run_002.png ├── run_003.png ├── run_004.png ├── run_005.png ├── run_006.png └── run_007.png命名规则是动作前缀_三位数字序号.png。前缀用英文单词表示动作类型比如 idle 待机、walk 行走、run 奔跑。三位数字序号保证文件排序稳定sort()后不会出现 10 排在 2 前面的问题。素材来源可以是 Photoshop、Aseprite、Spine、Live2D 导出的序列帧也可以是手绘扫描后统一裁剪的图片。关键要求是每张图片背景必须是透明 PNG。所有图片尺寸保持一致否则合成雪碧图后会出现错位。角色主体在画面中的位置尽量一致否则播放时会有明显抖动。3. 帧动画核心原理帧、帧率与动作节奏3.1 单帧、序列帧与雪碧图“单帧”就是一张静态图片。“序列帧”是一组按顺序编号的静态图片代表一个连续动作。“雪碧图”则把多张单帧按网格排列拼到一张大图里例如 4 张待机帧横向排成一张宽图或者 4×2 排列成网格。使用雪碧图的好处是减少图片文件数量。在游戏引擎里加载一张纹理图集比加载几十张小图要高效得多而且可以大大减少 DrawCall绘制调用次数。尤其在移动端纹理切换越少渲染压力越小。下面是一个常见的横向雪碧图示意| 帧1 | 帧2 | 帧3 | 帧4 | 帧5 | 帧6 |一行排开是最简单的排列方式。如果帧数很多比如 24 帧建议用多行排列每行固定数量保证引擎能按“列数 × 帧宽”的方式正确切出每一帧。3.2 帧率对动画流畅度的影响帧率也就是每秒播放多少帧单位是 FPS。帧率越大动画越顺滑但制作成本也越高因为你需要更多中间帧。8~10 FPS适合像素风、复古风格动画或者远程省略效果。12 FPS2D 手绘动画的常用档位足以表现走路、待机。24 FPS电影和多数手绘动画的标准帧率非常顺滑。30 FPS 及以上3D 游戏或高质量 2D 游戏常用但对序列帧数量要求很高。如果你想减少工作量可以用“帧延时”来模拟不同速度同一套帧每次播放停留 2 帧的时间动画速度就慢一倍。在脚本里这个需求对应一个fps参数后面实战部分会用到。3.3 待机、行走、奔跑的动作规律与帧数设计不同动作有各自的设计规律帧数不是随便定的。待机Idle看起来简单但做不好会非常僵硬。好的待机动画通常包含微微的呼吸起伏、眨眼、身体重心轻微晃动。基础待机建议 4~8 帧第 1 帧身体自然直立重心居中。第 2 帧胸部微扩身体轻微向上。第 3 帧还原到起始状态。第 4 帧重心下沉一点点或者加入一次眨眼。行走Walk是一个循环动作至少需要 6 帧才能看出左右脚交替。核心关键帧包括触地帧前脚掌接触地面身体重心在支撑腿上方。过步帧一条腿支撑另一条腿向前迈。上抬帧后脚跟抬起准备向前摆动。下落帧前脚掌落地。奔跑Run和行走最大的区别是奔跑有腾空帧身体前倾更明显手臂摆动幅度更大步幅也更长。建议 6~10 帧起始帧前脚伸出后脚蹬地。腾空帧双脚离地身体完全悬空。落地帧前脚着地身体重心压到最低。复位帧身体恢复进入下一轮循环。掌握了这些规律你就能检查自己的素材够不够、缺了哪些关键动作而不是盲目堆帧数。4. 实战一键生成待机、行走、奔跑帧动画4.1 创建项目结构在任意目录下创建项目文件夹结构如下frame-animation/ ├── assets/ │ └── frames/ # 原始序列帧图片 ├── output/ # 生成的雪碧图与配置文件 ├── tools/ │ ├── sprite_sheet.py # 雪碧图合成工具 │ ├── build_actions.py # 一键生成动作脚本 │ └── preview.py # Pygame 预览脚本 └── requirements.txt创建文件夹的命令mkdir -p frame-animation/assets/frames mkdir -p frame-animation/output mkdir -p frame-animation/tools cd frame-animation然后把你的序列帧图片复制到assets/frames目录下。如果还没有素材可以先随便用 3 张小尺寸 PNG 测试流程重点是先把脚本跑通。4.2 编写雪碧图合成工具在tools/sprite_sheet.py中实现一个基础工具输入一组帧图片输出一张合成后的雪碧图。# 文件路径tools/sprite_sheet.py import os from PIL import Image def build_sprite_sheet(images, colsNone): 将多张图片按网格排列合成一张雪碧图。 images: 按顺序排列的 PIL Image 对象列表 cols: 每行图片数量默认一行排开 if not images: raise ValueError(没有任何图片可供合成) frame_w, frame_h images[0].size if cols is None: cols len(images) rows (len(images) cols - 1) // cols sheet_w frame_w * cols sheet_h frame_h * rows sheet Image.new(RGBA, (sheet_w, sheet_h), (0, 0, 0, 0)) for index, img in enumerate(images): x (index % cols) * frame_w y (index // cols) * frame_h sheet.paste(img, (x, y)) return sheet def load_frames_from_folder(folder): 从文件夹中按文件名顺序加载 PNG 图片。 建议文件命名action_001.png、action_002.png ... files sorted( f for f in os.listdir(folder) if f.lower().endswith((.png, .jpg, .jpeg)) ) images [] for name in files: img Image.open(os.path.join(folder, name)).convert(RGBA) images.append(img) return files, images def save_sheet(sheet, output_path): 保存雪碧图并自动创建输出目录。 os.makedirs(os.path.dirname(output_path), exist_okTrue) sheet.save(output_path) print(f[OK] 雪碧图已保存{output_path})这里有几个细节需要注意所有帧图片必须保持相同尺寸脚本读取第一张图片的宽高作为统一尺寸如果后续图片尺寸不同合成时会被拉伸或错位。透明通道统一转成 RGBA 模式防止图片模式不一致导致合成异常。排序用sorted()对文件名排序所以文件名里的序号位数保持一致很重要建议统一用三位数字。4.3 编写一键生成动作脚本有了基础合成工具就可以写“一键生成”脚本。脚本要完成三件事扫描assets/frames目录下的所有帧图片。根据文件名前缀自动区分动作类型例如idle_*、walk_*、run_*。为每个动作生成对应的雪碧图并输出一份包含帧数、建议 FPS 的配置文件。# 文件路径tools/build_actions.py import os import re import json from collections import defaultdict from sprite_sheet import build_sprite_sheet, load_frames_from_folder SOURCE_DIR os.path.join(.., assets, frames) OUTPUT_DIR os.path.join(.., output) # 动作类型对应的默认播放速度 ACTION_FPS { idle: 6, walk: 10, run: 12, attack: 12, jump: 8, } def parse_action(filename): 从文件名中解析动作前缀。 例如 idle_001.png - idlewalk_002.png - walk match re.match(r([a-z])_(\d)\.png, filename.lower()) if match: return match.group(1) return None def group_frames_by_action(folder): 按动作前缀对帧文件分组并保持每个动作内帧顺序稳定。 groups defaultdict(list) files, _ load_frames_from_folder(folder) for name in files: action parse_action(name) if action is None: continue seq_num int(re.search(r_(\d)\.png, name.lower()).group(1)) groups[action].append((seq_num, os.path.join(folder, name))) # 按序号排序 for action in groups: groups[action].sort(keylambda x: x[0]) return groups def main(): if not os.path.isdir(SOURCE_DIR): print(f[Error] 找不到素材目录{SOURCE_DIR}) return os.makedirs(OUTPUT_DIR, exist_okTrue) groups group_frames_by_action(SOURCE_DIR) if not groups: print([Error] 素材目录下没有任何可识别的帧图片) return manifest {} for action, frame_items in groups.items(): # 重新按顺序加载图片 images [] for _, path in frame_items: from PIL import Image images.append(Image.open(path).convert(RGBA)) sheet build_sprite_sheet(images, colslen(images)) sheet_path os.path.join(OUTPUT_DIR, fsheet_{action}.png) save_sheet(sheet, sheet_path) manifest[action] { sheet: fsheet_{action}.png, frame_count: len(images), fps: ACTION_FPS.get(action, 10), frame_width: images[0].size[0], frame_height: images[0].size[1], } print(f[OK] 动作 {action}共 {len(images)} 帧推荐 FPS{manifest[action][fps]}) # 输出配置文件 manifest_path os.path.join(OUTPUT_DIR, actions.json) with open(manifest_path, w, encodingutf-8) as f: json.dump(manifest, f, ensure_asciiFalse, indent2) print(f[OK] 配置文件已生成{manifest_path}) def save_sheet(sheet, output_path): os.makedirs(os.path.dirname(output_path), exist_okTrue) sheet.save(output_path) if __name__ __main__: main()在tools目录下运行cd tools python build_actions.py预期输出效果[OK] 动作 idle共 4 帧推荐 FPS6 [OK] 动作 walk共 6 帧推荐 FPS10 [OK] 动作 run共 7 帧推荐 FPS12 [OK] 配置文件已生成../output/actions.jsonactions.json内容类似下方这样引擎或预览脚本可以直接读取{ idle: { sheet: sheet_idle.png, frame_count: 4, fps: 6, frame_width: 128, frame_height: 128 }, run: { sheet: sheet_run.png, frame_count: 7, fps: 12, frame_width: 128, frame_height: 128 }, walk: { sheet: sheet_walk.png, frame_count: 6, fps: 10, frame_width: 128, frame_height: 128 } }每次素材更新只要重新运行build_actions.py雪碧图和配置就会自动刷新。这就是“自定义动作一键生成”的核心思路用文件名规则驱动批量处理无需手动打开 PS 拼图也不用在引擎里手动画帧格。4.4 用 Pygame 预览动画光有雪碧图还不够最好能立刻看到动画效果。写一个 Pygame 预览脚本它可以直接播放单张雪碧图内的每一帧也可以直接从原始帧文件夹读取并循环播放。下面以直接播放原始帧文件夹为例方便你随时换素材观察效果# 文件路径tools/preview.py import os import sys import pygame # 需要传入参数帧图片所在目录例如 assets/frames 下的一个动作文件夹 def load_frames(folder): files sorted( f for f in os.listdir(folder) if f.lower().endswith((.png, .jpg, .jpeg)) ) frames [] for name in files: path os.path.join(folder, name) frames.append(pygame.image.load(path).convert_alpha()) return frames def preview_frames(folder, fps10, scale2): pygame.init() frames load_frames(folder) if not frames: print(没有可用帧图片) return frame_w frames[0].get_width() frame_h frames[0].get_height() screen_w frame_w * scale 40 screen_h frame_h * scale 40 screen pygame.display.set_mode((screen_w, screen_h)) pygame.display.set_caption(Frame Animation Preview) clock pygame.time.Clock() index 0 running True while running: for event in pygame.event.get(): if event.type pygame.QUIT: running False elif event.type pygame.KEYDOWN: if event.key pygame.K_ESCAPE: running False elif event.key pygame.K_SPACE: # 空格暂停/继续 pygame.event.pump() screen.fill((30, 30, 30)) frame frames[index] scaled_frame pygame.transform.scale( frame, (frame_w * scale, frame_h * scale) ) screen.blit(scaled_frame, (20, 20)) pygame.display.flip() index (index 1) % len(frames) clock.tick(fps) pygame.quit() if __name__ __main__: folder sys.argv[1] if len(sys.argv) 1 else asset_frames fps_arg int(sys.argv[2]) if len(sys.argv) 2 else 10 preview_frames(folder, fpsfps_arg)运行方式python tools/preview.py assets/frames/idle_001.png所在目录 比如:实际问题是我们素材是统一放在assets/frames目录下的文件名是idle_001.png、walk_001.png。此时直接传入assets/frames会混着多个动作。为了方便演示你可以临时把某个动作的帧单独放一个子目录例如mkdir -p assets/preview_idle cp assets/frames/idle_*.png assets/preview_idle/ python tools/preview.py assets/preview_idle 8这样就能看到待机动画以 8 FPS 循环播放。如果想看走路就把idle换成walk。4.5 运行效果与参数调整在脚本里主要可以调两个参数参数作用建议fps动画每秒播放帧数待机 6-8行走 10-12奔跑 12-15scale预览窗口放大倍数素材较小或像素风时建议 2-4调整方式很简单。比如想看清楚跑动动作的腾空细节可以降低为 8 FPS 逐帧观察不想让动画显得太快就按需减小 FPS。如果角色的动作幅度比较大高 FPS 会显得更流畅代价是需要更多中间帧。5. 进阶把帧动画接入游戏引擎5.1 Cocos Creator 中的帧动画配置思路Cocos Creator 中做帧动画常见流程是把雪碧图切成多个 SpriteFrame然后拖到 Animation 时间轴上。操作步骤大致如下将生成的sheet_idle.png导入到assets/resources目录。选中图片资源在资源管理器中右键选择“切割”设置 4 列、1 行或直接按宽高切割成单帧。为角色根节点添加 Animation 组件。在动画编辑器中创建 Clip比如取名为Idle。把切割好的 SpriteFrame 按顺序拖到同一帧轨道上设置每帧持续时间比如0.1秒对应 10 FPS。循环模式设置为Loop。使用代码动态切换动画时可以维护一个简单的动画状态字符串idle - walk - run什么时候播放什么动画取决于角色的移动速度、是否在空中、是否受击。这套状态切换逻辑可以写在动画组件回调里也可以由游戏逻辑层驱动。5.2 Unity 中的 Sprite 动画配置思路Unity 里同样是基于 Sprite 切割 Animation Clip 的方案导入sheet_walk.png把 Texture Type 设置为Sprite (2D and UI)。在 Sprite Editor 里按网格切片或者用自定义尺寸切片。创建 Animation Clip把切割好的 Sprite 依次加入帧序列。在 Animator 中建立参数比如Speed用来切换 Idle、Walk、Run 三个 Clip。用 Blend Tree 或直接根据参数做状态转移。需要特别注意的是Unity 中同一张 PNG 如果要在运行时切割通常需要把每帧的 Sprite 子资源导出或者使用 SpriteAtlas 做图集管理。切割完后一定要在动画窗口里确认每帧内容没有串位特别是多行动图时网格切分很容易错位。引擎接入部分不是本文展开重点这里更想强调一个原则生成雪碧图时尽量使用统一的网格布局并且把帧数、帧宽、帧高记录到配置文件里这样不管接入哪个引擎都能快速算准切图位置。6. 常见问题与排查思路6.1 动画播放速度不对问题现象常见原因解决思路动画太快FPS 设置过高降低 FPS 或增加帧数动画太慢FPS 设置过低或引擎里每帧停留时间偏长提高 FPS或检查引擎帧率走路像跑步帧数太少两帧之间跨越幅度过大增加中间帧或降低播放速度跑步像走路缺少腾空帧或身体前倾不明显在素材中加入腾空帧调整身体角度排查时先用预览脚本确定一个合理的速度再把这个速度同步到引擎配置里避免在引擎里反复盲调。6.2 图片边缘有黑边或白边这是帧动画最常见的显示问题。很多草绘角色在透明背景上播放时边缘会出现一圈黑边或浅色边非常影响观感。产生原因一般是原图在去背景时留下了半透明残留。导出时压缩格式导致透明通道信息丢失。引擎中纹理压缩格式不支持高质量透明比如某些移动端硬件压缩格式会把 RGB 和 Alpha 分开处理。解决方法尽量导出高分辨率 PNG不要直接压缩成 JPG。在引擎中关闭纹理的 Alpha 抖动或使用支持透明通道的压缩格式。手工处理素材时用 Photoshop 的“去除白边”或“描边”功能修一遍。6.3 帧动画占用内存过高帧动画本质是“多张完整图”如果帧尺寸大、帧数多、分辨率高内存占用会非常夸张。优化方向有四个缩小单帧尺寸。角色在实际屏幕上只需要 200×200就不要用 2000×2000 的大图。减少帧数。不是所有动作都需要 30 FPS2D 手绘动画 12 FPS 完全可以接受。使用图集。把多个动作的帧拼成一张大图减少纹理切换。按需加载。进入场景才加载需要的动画资源离开场景及时释放。在移动端尤其要注意内存峰值。帧数多、大尺寸的角色动画建议使用 Unity Addressables 或 Cocos 的资源异步加载。6.4 角色动作看起来僵硬动作僵硬通常不是脚本问题而是素材设计问题。几个容易踩坑的点没有关键帧意识。走路动作如果只有“左脚在前”和“右脚在前”两帧看起来就像滑冰而不是走路。缺少重心起伏。走路时身体有轻微上下起伏待机时身体也有呼吸起伏。循环衔接没对齐。最后一帧和一帧之间差异太大循环播放时会跳变。建议回看 3.3 节的动作设计规律把关键帧补齐。必要时可以把动画帧导出成一张表逐帧对比相邻帧的差异找到跳变点。7. 最佳实践与工程建议7.1 素材命名与目录规范统一命名规则是帧动画自动化流程的前提。推荐规则动作前缀用小写英文idle、walk、run、attack、jump、hurt。序号统一三位数001、010保证字典序和自然序一致。一个动作对应一个前缀不要混合命名。预留版本目录比如v1.0/frames/方便多版本素材管理。如果项目有多个角色建议结构按角色分目录assets/characters/knight/frames/idle_001.png assets/characters/knight/frames/walk_001.png assets/characters/knight/frames/run_001.png这样一键生成脚本也可以参数化传入角色目录即可。7.2 图集与合批优化把帧动画的所有动作拼成一张大图或者在引擎中利用图集工具打包能显著减少渲染性能消耗。2D 游戏每切换一次纹理GPU 就要切换渲染状态频繁切换会拖低性能。建议方案按角色打包图集不要所有角色混在一张图里。打包时预留一些空白区域避免后续增加帧时整个图集重排。在引擎里设置 Texture 的Generate Mip Maps为关闭2D 动画通常不需要 MipMap。压缩格式优先选择带透明通道的压缩格式根据目标平台设置。7.3 动作设计经验下面几条经验来自实际项目踩坑比较通用待机动画不意味着“不动”。加 1~2 帧呼吸变化、眨眼表情角色就有生命力。行走和奔跑不必完全重画。可以通过调整播放速度、身体前倾角度、手臂摆动幅度共享部分中间帧。攻击动作建议分“前摇-打击-收招”三段只在前摇和收招加帧打击帧干脆利落。用帧延时模拟慢动作。同一套行走帧10 FPS 是走路6 FPS 是潜行3 FPS 接近慢动作回放。循环动画的最后一帧和第一帧要尽量接近否则循环点会有跳变。7.4 自动化与版本管理帧动画生产如果完全靠手工容易出现“素材文件夹存了 50 个版本的 idle_001.png”这类混乱。建议把合成脚本纳入版本管理让流程可重复脚本统一放在tools/目录和素材同步提交到 Git。输出文件output/建议单独管理或只在发布版本时提交。每次修改素材后运行一次一键生成脚本并及时检查actions.json中的帧数变化。在 CI 流程中可以加一步“文件格式校验”检查没有大尺寸异常图片确保资源不失控。8. 总结与下一步帧动画并不是什么神秘的高深技术核心就是“按顺序播放一组图片”。但要做好看、做高效需要理解动作规律、帧率选择、素材管理和批量工具设计。本文以一个可复现的 Python 脚本为主线完成了三件事把命名规范的序列帧按动作分组。一键合成多个动作的雪碧图并生成 JSON 配置。用 Pygame 快速预览动画效果。这套流程跑通后你可以继续向三个方向深入如果你偏游戏开发下一步应该学习 Cocos Creator 或 Unity 的动画状态机把生成的雪碧图接入实际角色控制逻辑实现“待机切换行走行走切换奔跑”的完整状态联动。如果你偏美术和工具链可以在这个脚本基础上增加图片自动裁边、透明边缘检测、尺寸校验等功能做成团队内部的动画导入工具。如果你想挑战性能优化可以研究纹理图集动态打包、GPU Instancing、骨骼动画混合等更复杂的渲染技术。不管哪个方向都建议先把现有的素材整理规范让一键生成脚本跑起来。只有把重复劳动交给脚本你才有更多时间投入到真正需要创造力的动画设计中去。希望这份实战笔记对你有所帮助。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑