본문으로 건너뛰기

스프라이트 피벗(기준점) 편집기 · 프레임별 원점

한 번의 클릭으로 프레임의 피벗을 픽셀 격자에 놓거나 태그 전체에 한꺼번에 정하세요. 피벗은 각 엔진의 원점 필드로 그대로 전달됩니다.

피벗(오리진, 앵커라고도 함)은 게임 오브젝트의 위치에 놓이는 프레임의 점입니다. 회전은 이 점을 중심으로 돌고, 크기가 다른 프레임은 이 점에서 맞춰집니다. Nerulio에서는 한 프레임, 선택, 태그, 전체 프레임을 대상으로 픽셀 격자 위를 클릭(P)해 정하고, 프레임 캔버스 기준 0~1로 저장했다가 내보낼 때 엔진마다의 필드로 씁니다. Unity, Phaser, PixiJS는 프레임별 피벗을 따를 수 있지만 Godot 노드는 오프셋이 하나뿐이므로, 대상마다 실제로 무엇을 받는지 아래 표에 정리했습니다.

스프라이트 시트, 번호 붙은 프레임, GIF·APNG 또는 .aseprite 파일을 끌어다 놓으세요
빈 Studio 열기
브라우저에서 처리하며 파일은 업로드되지 않습니다.
Studio 스프라이트 작업 공간: 피벗·히트박스·허트박스가 있는 프레임과 애니메이션 태그가 있는 타임라인
CC0 에셋(OpenGameArt)을 연 실제 Studio 화면입니다.
내보내기 대상
  • Godot 4검증됨· Godot 4.7.2
  • Unity 6검증됨· Unity 6000.5.3f1
  • Phaser 3 / 4검증됨· Phaser 3.90 + 4.2
  • PixiJS 8검증됨· PixiJS 8.21
  • Aseprite JSON검증됨· Phaser load.aseprite · PixiJS 8.21
  • .aseprite검증됨· Aseprite 1.3.18
  • Spine / libGDX검증됨· spine-canvas 4.2
  • Starling / Sparrow XML검증됨· Phaser 4.2
  • LÖVE검증됨· LÖVE 11.5
  • Defold빌드 확인· Defold bob.jar 1.13.1
  • GameMaker미검증
  • CSS sprites검증됨· Chromium
  • GIF / APNG디코딩 확인· Pillow

피벗 값은 하나, 엔진 규칙은 여럿

엔진마다 피벗을 세는 방식이 다릅니다. Unity는 스프라이트 사각형의 왼쪽 아래에서 0~1(Normalized) 또는 픽셀로 잽니다. Phaser와 PixiJS는 y가 아래로 가는 프레임 기준 0~1입니다. Godot의 AnimatedSprite2D에는 피벗이 없고 노드 전체에 대한 픽셀 단위 그리기 오프셋만 있습니다. Nerulio는 값 하나(프레임 캔버스 기준 0~1, y는 아래 방향, 따로 정하지 않으면 아래 가운데 0.5, 1.0)만 저장하고 대상마다 변환하므로, 한 번 정한 피벗이 트림·패킹·엔진 변경 뒤에도 유지됩니다.

프레임 크기가 다르거나 트림되면 프레임별 피벗이 중요해집니다. 그래서 Godot 씬은 첫 프레임의 피벗을 노드 오프셋으로 쓰고, 모든 프레임의 피벗을 리소스 메타데이터에 남기며, 한 애니메이션 안에서 피벗이 다르면 경고합니다. 어느 엔진에서든 튼튼한 구성은 프레임을 한 캔버스에 두고 태그마다 발에 피벗 하나를 두는 것입니다.

피벗 도구는 정수 픽셀에 맞춰지고, 프레임을 정렬·반전·흔들림 보정할 때 그림과 함께 움직입니다.

피벗 / 오리진 / 앵커
오브젝트 위치에 놓이는 프레임의 점. 엔진에 따라 이름이 다릅니다.
정규화 피벗
프레임이나 스프라이트 사각형 기준 0~1. Unity는 y를 아래에서, Phaser와 PixiJS는 위에서 셉니다.
노드 오프셋(Godot)
AnimatedSprite2D가 텍스처를 노드 원점에서 떨어뜨려 그리는 픽셀 값. 모든 프레임에 하나.

예시: 피벗 하나를 엔진 다섯 곳에 쓰기

48 × 64 프레임 캔버스, 피벗은 아래 가운데. 패커가 서 있는 프레임을 (14, 34)의 20 × 30으로, 점프 프레임을 (14, 20)의 20 × 30으로 트림합니다.

Nerulio           피벗 (0.5, 1.0), 48 × 64 기준  → 픽셀 (24, 64)
Godot .tscn       centered = false, offset = (−24, −64)
Phaser / PixiJS   pivot / anchor (0.5, 1.0), 48 × 64 원본 프레임 기준
LÖVE              px = 24, py = 64
Unity, 서기       ((24 − 14) ÷ 20, (30 − (64 − 34)) ÷ 30) = (0.5, 0.0)
Unity, 점프       ((24 − 14) ÷ 20, (30 − (64 − 20)) ÷ 30) = (0.5, −0.467)

점프 프레임의 Unity 피벗은 자기 사각형보다 아래에 있습니다. 바로 그 덕분에 발이 같은 자리에 머뭅니다. 트림이 피벗을 옮기는 이유는 트림 후 스프라이트 흔들림에서 설명합니다.

대상마다 받는 것

대상Nerulio가 쓰는 것엔진이 하는 일
Godot 4씬: centered = false, offset = 첫 애니메이션 첫 프레임의 −피벗. 모든 프레임의 피벗은 metadata/nerulioAnimatedSprite2D는 모든 프레임을 그 오프셋 하나로 그림. 프레임별 피벗은 직접 스크립트 필요
Unity 6스프라이트마다 사용자 피벗, 스프라이트 사각형 기준 0~1, y는 위 방향(트림된 프레임은 0~1 밖일 수 있음)스프라이트마다 피벗을 가지므로 클립이 프레임과 함께 피벗을 바꿈(Unity 6000.5.3f1에서 다시 읽어 확인)
Phaser 3 / 4아틀라스 JSON의 프레임별 pivot {x, y}Phaser 3.90은 프레임의 사용자 피벗으로 표시하고, 애니메이션 프레임을 포함해 프레임이 바뀔 때마다 setOrigin을 호출
PixiJS 8프레임별 anchor {x, y}텍스처의 기본 앵커가 됨. Sprite는 만들 때 가져가고, AnimatedSprite는 updateAnchor = true일 때만 프레임마다 따름
Aseprite JSON, .aseprite피벗이 바뀌는 프레임에 키가 있는 pivot 슬라이스Aseprite에서 피벗 점이 있는 슬라이스로 보임
LÖVE 11Lua 프레임 표의 px, py함께 온 nerulio_atlas.lua가 각 프레임의 피벗을 (x, y)에 맞춰 그림
GameMaker태그마다 스트립 하나, 모든 피벗을 한 점에 맞춤. 그 점이 gamemaker.json과 README의 오리진Sprite Editor에서 스프라이트의 Origin으로 입력(GameMaker에서는 UNVERIFIED)
Defold, Spine / libGDX, CSS피벗 없음엔진에서 설정

Starling / Sparrow XML에도 픽셀 단위 pivotX, pivotY가 들어가지만, 쓰는지는 읽는 쪽에 달려 있습니다.

이렇게 작동합니다

  • 피벗 도구(P): 클릭하면 현재 프레임의 픽셀 격자에 맞춰 놓입니다.
  • 적용 범위: 이 프레임, 선택한 프레임, 태그, 전체 프레임.
  • 정렬하거나 뒤집어도 피벗은 그림에 붙어 따라갑니다.
  • 내보내기: Godot 씬 오프셋, Unity 스프라이트 피벗, PixiJS anchor, Aseprite 슬라이스 피벗, GameMaker origin.

사용 방법

  1. 스프라이트를 넣고 가져오기를 적용합니다.
  2. 프레임 패널에서 범위를 고르고 P를 누릅니다.
  3. 발(또는 가운데)이 올 자리를 클릭하고 화살표 키로 미세 조정합니다.
  4. 엔진용으로 내보내면 피벗이 그 형식으로 기록됩니다.

결과 확인

  • 어니언 스킨(F3)을 켜고 태그를 넘겨 봅니다. 피벗 십자가 몸의 같은 자리에 머물러야 합니다.
  • Godot: 내보내기 안내(피벗 불일치 경고)를 읽고, print($Hero.sprite_frames.get_meta("nerulio"))로 프레임마다의 피벗을 봅니다.
  • Unity: Sprite Editor에서 텍스처를 열면 스프라이트마다 Pivot이 Custom이고 값은 예시의 정규화 값입니다.
  • Phaser: sprite.play('run') 뒤에 sprite.originX, sprite.originY가 현재 프레임의 피벗과 같습니다.

문제 해결

증상유력한 원인확인 방법해결
Godot에서 애니메이션이 바뀔 때 캐릭터가 튐노드 오프셋은 첫 애니메이션 첫 프레임에서 온 하나뿐인데 다른 애니메이션은 피벗이 다름Godot 내보내기 안내, metadata/nerulio의 피벗 비교캐릭터의 모든 태그에 피벗 하나를 쓰거나, 애니메이션이 바뀔 때 스크립트로 메타데이터에서 offset을 설정
PixiJS AnimatedSprite가 프레임별 피벗을 무시함updateAnchor가 기본값 false라 첫 텍스처의 앵커가 유지됨sprite.updateAnchor 값을 출력updateAnchor = true로 두거나 태그에 피벗 하나만 쓰기
Unity 피벗이 0보다 작거나 1보다 큼트림된 프레임이라 전체 캔버스 기준 피벗이 작아진 사각형 밖에 있음Sprite Editor의 Custom Pivot 값고칠 필요 없음. 그래야 그림이 맞춰짐. 0~1이 꼭 필요한 도구라면 트림을 끄고 패킹

다른 방법

방법이럴 때 더 낫습니다
엔진에서 피벗 설정(Unity Sprite Editor Pivot, GameMaker Origin, Godot 노드 오프셋)피벗이 하나뿐인 스프라이트를 거의 다시 내보내지 않을 때.
Aseprite의 피벗 슬라이스피벗을 .aseprite 원본에 두고 싶을 때. Nerulio는 가져올 때 피벗 슬라이스를 읽고 .aseprite와 Aseprite JSON에 다시 씁니다.

엔진별 내보내기와 검증 방법

"검증됨"은 실제 CC0 에셋으로 내보낸 파일을 해당 엔진·도구가 직접 불러와 원본과 비교했다는 뜻입니다. 불러오지 않은 형식은 그렇게 표시합니다.

대상파일검증
Godot 4.tres SpriteFrames · .tscn AnimatedSprite2D · .png.import검증됨 Godot 4.7.2Godot가 불러와 모든 애니메이션 프레임을 그려 원본과 비교했습니다. 씬은 Nearest 필터를 쓰고 회전은 쓰지 않습니다.
Unity 6.unity.json · Editor/NerulioSpriteImporter.cs · AnimationClip검증됨 Unity 6000.5.3f1배치 모드에서 스프라이트 영역·피벗·픽셀·클립 키·길이를 확인했습니다.
Phaser 3 / 4atlas JSON (multiatlas) · .anims.json검증됨 Phaser 3.90 + 4.2두 버전 모두에서 프레임과 애니메이션을 그렸습니다.
PixiJS 8spritesheet JSON · animations · anchor · meta.scale검증됨 PixiJS 8.21회전·여러 페이지 아틀라스도 포함해 확인했습니다.
Aseprite JSONhash / array · frameTags · slices검증됨 Phaser load.aseprite · PixiJS 8.21태그의 방향과 반복 횟수가 유지됩니다.
.asepritelayers · tags · durations · slices검증됨 Aseprite 1.3.18Aseprite 명령줄로 열어 렌더링했습니다.
Spine / libGDX.atlas검증됨 spine-canvas 4.2Spine 런타임이 회전·트림 영역을 모두 그렸습니다. libGDX 자체는 실행하지 않았습니다.
Starling / Sparrow XMLXML per page검증됨 Phaser 4.2Phaser 3.90은 트림된 XML 프레임을 잘못 그립니다(Phaser 버그). "Sparrow XML (Phaser 3)" 프리셋은 트림을 끄며 3.90·4.2 모두 통과합니다.
LÖVELua quads · nerulio_atlas.lua · main.lua검증됨 LÖVE 11.5포함된 헬퍼로 모든 프레임을 그리고 모든 애니메이션을 재생했습니다.
Defold.atlas · .tilesource빌드 확인 Defold bob.jar 1.13.1Defold 명령줄 빌더로 빌드하고 빌드된 텍스처의 UV를 다시 읽어 확인했습니다.
GameMakerspr_<name>_stripN.png · gamemaker.json미검증GameMaker에서 불러오지 않았습니다(헤드리스 실행 불가). 스트립은 GameMaker 스트립 가져오기 방식대로 자릅니다.
CSS sprites.css · preview .html검증됨 Chromium포함된 스타일시트로 모든 클래스를 그렸습니다.
GIF / APNGone file per animation디코딩 확인 Pillow내보낸 뒤 모든 프레임과 지연 시간을 다시 디코딩했습니다. APNG는 원본과 동일합니다.

검증 근거

GIF 디코더: 실제 GIF 29개 408/408프레임이 Pillow와 동일, APNG 16개 132/132프레임. .aseprite: 코퍼스 231개 파일을 가져와 다시 쓰고 Aseprite 1.3.18로 열었을 때 태그·길이·픽셀 231/231 일치. 내보내기: 실제 CC0 에셋으로 실제 엔진에서 49회 실행해 47회 통과. 실패 2회는 Phaser 3.90의 트림 XML 버그이며 Phaser 3 프리셋으로 피합니다.

한계

  • Godot는 스크립트를 쓰지 않는 한 프레임별이 아니라 노드마다 피벗 하나를 받습니다.
  • Defold, Spine / libGDX, CSS 내보내기에는 피벗이 없습니다.
  • GameMaker 오리진은 GameMaker 자체에서 UNVERIFIED입니다.
  • 격자·섬 인식은 신뢰도가 표시된 미리보기일 뿐이며 적용을 누르기 전에는 아무것도 자르지 않습니다. 모든 선택에는 한 번에 바꿀 수 있는 대안이 있습니다.
  • 레이어가 정확히 합성되지 않는 .aseprite 파일(그룹 불투명도 등)은 합쳐서 가져오고, 가져오기 패널에 이유를 표시합니다.
  • 가져온 아틀라스에서 회전된 프레임은 회전된 채로 남으며 그 내보내기는 미검증입니다.
  • 이미지는 한 변 32,768px(2억 6,800만 픽셀)까지이며 브라우저 메모리에 따라 달라집니다.

버전과 출처

Unity 6000.5.3f1이 모든 스프라이트의 피벗을 다시 읽었고, 공통 기준점에 대해 그림이 원래 자리에 놓였습니다. Godot 4.7.2는 오프셋이 있는 씬을 불러왔습니다. Phaser와 PixiJS가 피벗으로 하는 일은 Phaser 3.90 소스와 PixiJS 8 문서에 따른 것이며, Nerulio가 실행해 본 결과는 아닙니다.

참고한 공식 문서

자주 묻는 질문

피벗은 픽셀인가요, 0~1인가요?

프레임 캔버스 기준 0~1로 저장하며 도구는 정수 픽셀에 맞춥니다. 엔진별 형식은 이 값에서 변환됩니다.

Unity에서도 프레임마다 피벗이 따로 들어가나요?

네. 포함된 가져오기 스크립트가 Unity 6 스프라이트 영역을 피벗과 함께 만듭니다(Unity 6000.5.3f1에서 확인).

무료인가요? 계정이 필요한가요?

이 페이지의 기능은 모두 무료이며 계정 없이 쓸 수 있습니다. 워터마크나 막혀 있는 내보내기가 없습니다.

스프라이트가 업로드되나요?

아니요. Studio는 이 브라우저 탭 안에서 디코딩·패킹·내보내기를 합니다. 프로젝트는 브라우저(IndexedDB)에 자동 저장되며 .nerulio 파일로 저장할 수 있습니다.

Aseprite나 엔진 플러그인을 설치해야 하나요?

아니요. .aseprite 파일은 브라우저에서 읽고 씁니다. 엔진별 번들에는 그 엔진에 필요한 것이 들어 있습니다(Godot는 가져오기 설정과 씬, Unity와 Godot 타일셋은 작은 편집기 스크립트).