Sprite sheet · 實測

GIF 轉 sprite sheet:匯入之前,先讓 AI 檢查每一格

一疊呈扇形展開的半透明象牙白紙張,上面有姿勢逐張變化的炭黑色小人偶,旁邊是同樣的紙張邊對邊排成一列,其中一張是琥珀色
原創抽象編輯插畫,於 Ciyo 中以 GPT Image 2.5 Sunburst 生成。

GIF 很適合用來分享動畫,卻不適合直接放進遊戲。Godot、Unity 和 Phaser 這類遊戲引擎需要的是 sprite sheet(精靈圖表):所有影格排在大小相同的格子裡,使用美術的實際像素尺寸,再加上每一格停留在畫面上的時間。GIF 也會把問題藏起來,直到動畫在遊戲裡循環播放才現形:一個重複的影格、一個偏移一像素的影格、一個停在錯誤位置的停頓。

2026 年 9 月 30 日,我們給 Ciyo Agent 一個 7 格的史萊姆跳躍 GIF,請它做出可以匯入的 sprite sheet。它讀了每一格,找出三個循環問題,並在我們要求後修好。每個檔案我們都自己檢查過。

遊戲引擎需要從 GIF 拿到什麼

三樣東西:以原生尺寸排在等大格子裡的影格;影格的尺寸和數量;以及每一格的持續時間。原生尺寸就是美術人員實際繪製的尺寸。很多像素畫 GIF 會以 4×、6× 或 8× 匯出,好在社群媒體上看起來清楚;用那個尺寸匯入不但浪費記憶體,縮放時還會變模糊。

Ciyo 裡的 Agent 能讀取附加 GIF 的每一格。這一點很重要,因為人用正常速度拖動播放 GIF 時,不會注意到某一格偏了一個像素。

該要求什麼,以及原因
要求原因
原生像素尺寸檔案裡的一個像素對應一個美術像素;任何整數倍放大都清晰
一列等大的格子引擎依照格子大小切割圖表
透明背景不需要去背色,也沒有殘留的色邊
每一格的持續時間GIF 各格的延遲常常不一樣
逐格檢查重複影格和抖動只有在循環播放時才看得出來

我們的測試 GIF:虛構平台遊戲中的史萊姆跳躍

我們為虛構的平台遊戲 Tumblebrook 做了一個小測試 GIF:一隻綠色史萊姆先壓扁、跳起再落地。它是 192 × 192 像素、7 格、4 種顏色,實際上是以剛好 6× 匯出的 32 × 32 美術。各格延遲從 80 到 200 毫秒不等,這種情況很常見。

我們故意把其中一格往右移了一個美術像素,看看 Agent 會不會發現。這個 GIF 的最後一格還是第一格的複本,這一點不在我們的計畫之內。

我們附上 GIF 時傳送的訊息
這個 GIF 是 Tumblebrook 的跳躍動畫,這是我用 Godot 做的小型平台遊戲。請把它轉成我可以匯入的 sprite sheet:一列、等大的格子、透明背景,使用美術的原生像素尺寸(不是 6x 的匯出版)。動手之前,請先看過每一格,告訴我影格數、每一格的延遲,以及任何在循環播放時會看起來不對的地方。把 sprite sheet 和一個記錄影格尺寸與持續時間的 JSON 檔存到畫板上。

Agent 在 7 格中找到了什麼

Agent 確認 192 可以被 6 整除,確認原生尺寸是 32 × 32,並做出一張 224 × 32 的圖表:七個格子排成一列,背景透明,沒有混色的邊緣像素。它列出了各格延遲:120、80、80、80、200、80 和 140 毫秒。

接著它回報了三個問題,三個都是真的。最後一格「pixel-for-pixel the same as frame 0」(和第 0 格逐像素完全相同),所以休息姿勢會在畫面上停留 260 ms,「the hop will seem to stall at the landing」(跳躍看起來會在落地時卡住)。第 5 格是第 3 格「moved 1 px right and 2 px down」(往右移 1 px、往下移 2 px)的複本,中心在 x = 17 而不是 16,所以史萊姆會往旁邊抽動一下。另外,第 5 格在下落時重複使用了上升的姿勢,所以底邊會一口氣跳 4 個像素進入落地畫面。

它也說明了自己做不到的事:畫板只接受圖片和影片,所以它無法把 .json 檔存在那裡。它提議改把 JSON 貼在對話中。

Ciyo 畫板上的史萊姆 sprite sheet,分別放在洋紅色棋盤格背景和透明背景上,Agent 面板列出重複的第一格、一像素的抖動和不順的落地
第一張圖表和 Agent 的逐格檢查:重複的第一格、1 像素的抖動和不順的落地。2026 年 9 月 30 日。

先修好循環,再匯出

我們請它做一張修好的圖表。動筆之前,Agent 先研究現有的影格,學會它們在外框線、邊角、陰影和高光上的規則。它甚至自我修正(「Highlight sits one pixel further in than I assumed」,高光比我原本以為的再往內一個像素),並逐像素重建三個原始影格,證明它掌握了這些規則。

修好的圖表有六格。重複的影格拿掉了,每一格的中心都在 x = 16,而且新增了一個 13 × 19 像素、拉長的下落姿勢,只下降 3 個像素進入落地格,而不是跳 4 個像素。現在整圈循環是 640 ms。Agent 也提醒,休息姿勢變短了(120 ms,原本是 260 ms),以防跳躍感覺太趕。沒有花任何點數。

兩列放大 8 倍的綠色像素史萊姆:上排是 GIF 原本的七格,下排是修好的六格,含一個新的高瘦下落姿勢
上:完全照 GIF 原樣的圖表(224 × 32)。下:含新下落姿勢的修正圖表(192 × 32)。以 8× 顯示。
修正的要求
好,麻煩了:請做出修好的 sprite sheet。拿掉重複的影格,把第 5 格移回中心,並給落地一個真正拉長的下落姿勢,不要重複使用上升的那一格。保持同樣的 4 種顏色和 32x32 的格子。然後把可以直接用在 Godot 的 JSON 貼在這裡(影格尺寸、影格數、每一格的持續時間),並存一個修好後循環的 6x 預覽 GIF,讓我看看效果。

JSON 和 Godot 設定

Agent 貼出一段 JSON,內容有圖片名稱、圖表尺寸(192 × 32)、影格尺寸(32 × 32)、排成一列的六格、每一格的區域和以毫秒計的持續時間,以及給 Godot 用的相對持續時間。因為每個延遲都是 40 ms 的倍數,它建議使用每秒 25 格的 SpriteFrames 動畫,相對持續時間為 3、2、2、2、5 和 2,並使用最近鄰濾鏡讓像素保持清晰。

把 JSON 存在專案中 PNG 的旁邊。如果你的引擎使用其他格式,就直接說出那個格式的名稱;真正重要的是影格清單。

Ciyo Agent 面板顯示貼出的 JSON,含六格和總長 640 ms,旁邊畫板上是舊圖表、修正圖表和一個 6 倍預覽
貼出的 JSON、Godot 設定建議,以及畫板上的修正圖表和它的 6× 預覽 GIF。

匯入任何 sprite sheet 前的五項檢查

不論圖表來自 AI、轉檔工具還是你自己的匯出,這些檢查都能抓出常見的問題。最後一欄是修好的 Tumblebrook 圖表。

sprite sheet 檢查項目,以及我們 2026 年 9 月 30 日修好的圖表
檢查項目方法修正後的圖表
原生尺寸GIF 尺寸 ÷ 匯出倍率是整數192 ÷ 6 = 32
沒有重複影格比較最後一格和第一格已移除重複影格
沒有抖動每一格的中心(或腳底線)相同六格中心都在 x = 16
色盤數顏色;背景是透明的4 種顏色加上透明
時間列出每個延遲;檢查休息姿勢的長度循環 640 ms,休息 120 ms

遊戲美術的下一步

乾淨的圖表放進引擎之後,用同樣的影格畫下一段動畫,讓風格保持一致,並在玩家實際看到的尺寸下檢查角色。

GIF 轉 sprite sheet

怎麼找出 GIF 的原生像素尺寸?

把 GIF 尺寸除以匯出倍率,確認結果是整數。我們 192 × 192 的 GIF 是以 6× 匯出的 32 × 32 美術。Agent 確認了每一格都能剛好縮小。

為什麼我的循環會卡住或抽動?

通常是最後多了一個重複的影格(休息姿勢停留的時間變成兩倍),或是某一格偏離中心一個像素。在我們的測試中,Agent 逐格比較後把兩個問題都找了出來。

Ciyo 畫板能存放 JSON 檔嗎?

不能。在 2026 年 9 月 30 日,畫板只接受 png、jpg、webp、gif、mp4 和 mov,所以 Agent 把 JSON 貼在對話中讓你自己存檔。

這樣花了多少?

在我們的測試中完全免費。讀取影格、做出兩張圖表、畫新的影格和預覽 GIF,全都在 Agent 的工作區裡完成,沒有用到圖像模型。

在 Ciyo 中檢查你的 GIF

附上你的動畫,告訴 Ciyo Agent 你用的引擎和匯出倍率,並請它在做出 sprite sheet 之前先檢查每一格。