이 페이지에서
에셋 저장소 구성
원본 트리 하나, 생성물 트리 하나, 에셋 빌드와 게임 사이의 어댑터 하나를 사용하세요. Ashfox 권장 컨벤션은 편집 입력을 asset/에, 지울 수 있는 출력을 루트 build/에 두는 것입니다. 이 이름은 기본값이며 예약 키워드가 아닙니다. 실제 경로는 워크스페이스에서 정합니다.
여기서 설명하는 코드형 워크스페이스와 그룹형 init 템플릿은 CLI 2.0.0부터 제공됩니다. 예전에 설치한 1.0.0 압축파일에는 자동으로 추가되지 않습니다. 기존 JSON 워크스페이스도 지원합니다. 체크섬이나 잠금 파일을 갱신하지 않고 고정된 압축파일을 바꾸지 마세요.
컨벤션으로 시작하기
ashfox init my-game
cd my-game
스타터는 오프라인으로 생성되며 기존 대상 폴더는 거부합니다. 설치 가이드에 따라 이 프로젝트 루트에 CLI를 설치하고 패키지·잠금 파일을 커밋하세요. 에셋 그룹마다 npm 프로젝트를 따로 만들지 마세요.
my-game/
.ashfoxworkspace.mjs executable build configuration, tracked
.gitignore ignores /build/ and /node_modules/
assets.mjs game build adapter, tracked
asset/
creatures/fox/
fox.ashfox model entry
body.ashfox imported geometry module
rig.ashfox imported skeleton and motions
surface.ashfox imported appearance module
items/
sword.ashfox sprite entry
shared.ashfox imported sprite module
sounds/
claw_hit.ashfox sound entry
build/
assets/
compiler/ canonical bundles and current.json
exports/
creatures/fox/ immutable delivery bundles
items/iron_sword/
sounds/claw_hit/
원본, 가져오는 모듈, 워크스페이스 코드, 통합 코드, 도구 잠금 파일을 Git에 보관합니다. 컴파일 영수증, 출력, 생성된 언어 바인딩, 리뷰 캡처, 캐시는 build/ 아래에 두고 Git에서 제외합니다. 직접 만든 참고 이미지는 추적되는 원본·참고 폴더에 둡니다. PNG 전체를 제외하지 마세요. 깨끗한 체크아웃과 고정된 도구로 build/의 모든 내용을 재생성할 수 있어야 합니다.
워크스페이스에 빌드 정책 작성하기
.ashfoxworkspace는 이식 가능한 JSON입니다. .ashfoxworkspace.mjs는 같은 버전 2 객체를 default export하는 실행 가능한 Node ESM입니다. 루트마다 하나를 선택하세요. 둘 다 있으면 조용히 선택하지 않고 거부합니다. 소스 빌드는 Git 루트까지 위로 탐색하며 두 형식 중 하나를 찾습니다. 관찰 명령은 기존처럼 소스만 다룹니다.
const items = [
{ name: 'iron_sword', path: 'sword.ashfox' },
];
export default {
format: 'ashfox-workspace', version: 2, name: 'my-game',
packages: [{
name: 'items', root: 'asset/items',
manifest: {
format: 'ashfox-package', version: 1,
entries: items,
modules: [{ subpath: './shared', path: 'shared.ashfox' }],
dependencies: [],
},
}],
include: ['asset/items/**/*.ashfox'], ignore: ['build/**'],
build: { directory: 'build/assets/compiler' },
exports: items.map(item => ({
name: `items_${item.name}`,
entry: { packageName: 'items', entryName: item.name },
format: 'png', directory: `build/assets/exports/items/${item.name}`,
})),
};
스타터의 아이템 소스를 위한 완전한 아이템 전용 설정입니다. 전체 스타터는 같은 매핑 방식으로 모델과 사운드도 처리합니다. 게임 매니페스트나 Minecraft 전달물이 필요하면 packs를 추가하세요. 일반 import와 함수로 정책을 분리할 수 있습니다. 콜백이 아닌 객체를 export하세요. 함수로 객체를 구성할 수 있지만 출력 데이터 내부의 함수는 지원되는 설정 계약이 아닙니다.
코드형 설정은 일반 Node 권한으로 실행하는 신뢰된 프로젝트 코드이며 샌드박스 에셋 DSL이 아닙니다. check·build에서 실행되며 상위 설정을 발견한 소스 빌드도 포함합니다. 낯선 저장소는 실행 전에 설정과 import를 리뷰하세요. stdout은 평가기의 결과용으로 남겨 두고 진단에는 stderr를 사용합니다. 평가는 워크스페이스 루트에서 실행되며 제한 시간은 10초, 캡처 출력은 256 KiB입니다. 알 수 없는 설정과 잘못된 경로는 동일한 엄격한 워크스페이스 검증에서 실패합니다. 실행하지 않는 설정이 필요하면 JSON을 사용하세요.
타임스탬프, 난수, 네트워크 응답, 고정되지 않은 환경값으로 에셋을 선택하지 마세요. 평가된 설정과 선택된 소스 바이트가 빌드 식별자에 반영됩니다. 발행 전에 설정을 다시 평가해 결과가 바뀌면 실패합니다. import한 설정 코드를 별도의 도구 잠금으로 기록하지는 않으므로 소스 커밋과 의존성 잠금을 보관하세요.
그룹과 안정적인 ID 선택하기
크리처·아이템·UI·사운드처럼 의미와 소유권을 기준으로 묶습니다. 복잡한 크리처에는 명확한 진입점과 import 모듈을 갖춘 전용 폴더를 주고, 작은 관련 스프라이트는 함께 둡니다. 파일 모양이 비슷하다는 이유보다 실제 계약을 공유할 때 공용 모듈을 추출하세요.
폴더는 편집을 정리하고 패키지·진입점 이름은 컴파일 대상을 선택하며 export ID는 어댑터의 계약이 됩니다. 스타터의 items_iron_sword는 소스가 이동해도 유지합니다. 스프라이트 진입점 이름은 선언된 스프라이트 ID와 일치해야 합니다. 선택된 파일은 모두 진입점이나 도달 가능한 모듈로 등록하세요. 모듈 import가 별도 export를 만들지는 않습니다. 같은 에셋 목록을 여러 카탈로그에 중복하지 마세요.
64개 export 상한은 없습니다. 임의 개수로 나누지 말고 독립된 소유권·전달·실행 예산이 필요할 때 워크스페이스를 나누세요. 모든 출력은 워크스페이스 루트 아래에 있어야 합니다. 루트 build/를 쓰려면 설정을 저장소 루트에 두세요. 중첩 설정에서 ../../build는 잘못된 경로입니다. 동시 빌드는 겹치지 않는 출력 디렉터리를 소유해야 합니다. 워크스페이스 설정과 CLI 제한의 소스·워커 예산은 계속 적용됩니다.
한 번 빌드하고 하나의 검증된 식별자 사용하기
npx --no-install ashfox build .ashfoxworkspace.mjs --json
npx --no-install ashfox verify build/assets/compiler --json
node assets.mjs
처음 두 명령은 내부 CLI 흐름을 보여줍니다. node assets.mjs가 두 작업을 모두 수행하므로 게임 파이프라인에서는 셋을 반복하지 말고 어댑터를 한 번 호출하세요. 기본 어댑터는 프로젝트 루트에 설치된 CLI를 사용합니다. Gradle 도구 환경은 체크섬으로 검증해 추출한 CLI 경로를 인자로 넘길 수 있습니다.
빌드는 bundleHash, bundlePath, catalogPath와 export 디렉터리를 반환합니다. 정식 카탈로그에는 에셋 ID·종류·상대 파일명·크기·해시가 기록됩니다. 어댑터는 선택된 빌드를 검증하고 빌드 응답과 해시가 같은지 확인한 뒤 그 정확한 불변 번들 안에서 파일을 찾습니다.
import { buildAssets } from './assets.mjs';
const built = buildAssets();
const asset = built.catalog.assets.find(item => item.id === 'items_iron_sword');
if (!asset) throw new Error('Missing required sword');
const png = asset.files.find(file => file.path.endsWith('.png'));
if (!png) throw new Error('Missing sword PNG');
const relative = png.path.slice(`assets/${asset.id}/`.length);
const source = built.file(asset.id, relative);
// Pass source to the game's resource copy/import step.
소스 파일명으로 출력 파일명을 조합하거나 가장 최근 파일을 스캔하지 마세요. 게임 빌드 중 에셋마다 current.json을 다시 읽지 말고 하나의 검증된 번들 식별자를 유지합니다. ID나 파일이 없으면 통합이 실패해야 합니다. 이전 번들이 디스크에 남아 있어도 에셋 빌드가 실패하면 게임 빌드를 중단하세요.
출력 경로 패턴은 안정적이지만 관련 입력이나 실행 프로필이 바뀌면 번들 해시도 바뀝니다. 같은 유효 입력, 고정된 컴파일러·Node/V8·OS/아키텍처·인코더 프로필에서 번들 해시를 재현합니다. 임의 머신 사이의 바이트 일치는 보장하지 않습니다.
게임 엔진에 연결하기
엔진 매핑은 편집하는 형상·픽셀과 분리된 어댑터 하나에 둡니다. Gradle에서는 에셋 어댑터를 입력을 생성하는 태스크로 실행하고 리소스 처리 태스크가 의존하게 하세요. 원본·설정·도구 입력과 소유하는 출력 디렉터리를 선언합니다. 성공한 선택 결과물만 게임 리소스 준비 영역으로 복사하세요. 생성 리소스를 asset/로 되돌려 넣지 마세요.
웹 게임은 런타임 어댑터로 game-assets 매니페스트를 사용합니다. Java·Kotlin·TypeScript에서는 프로젝트 어댑터가 build/generated/assets/ 아래에 상수나 타입 참조를 생성할 수 있습니다. 언어 바인딩 생성과 엔진별 빌드 플러그인은 내장 CLI 기능이 아닙니다. 워크스페이스도 임의의 빌드 후 훅을 제공하지 않습니다. 워크스페이스는 컴파일과 전달을 선언하고, assets.mjs가 소비 측 통합을 담당합니다.
공개와 컴파일을 분리하세요. 필요하면 엔진 어댑터에서 포맷을 변환할 수 있지만 변환 코드는 버전 관리와 검증이 필요합니다. 일반적인 exporter 결함은 크리처별 불명확한 출력 패치를 쌓기보다 Ashfox에서 고치세요.
리뷰·정리·업그레이드
캡처와 동작 미리보기는 build/review/<asset-id>/ 아래에 두고 소스 커밋·번들 해시와 연결합니다. Git diff와 시청각 변화를 함께 리뷰하세요. 컴파일만으로 외형이나 게임 호환성을 보장하지 않습니다.
빌드가 소유한 디렉터리만 정리합니다. 저장소 전체에서 build/를 생성 데이터 전용으로 쓰고 실행 중인 빌드가 없을 때는 루트 build/를 지울 수 있습니다. 추적 중인 에셋, 임의의 인접 폴더, 다른 프로세스가 사용 중인 출력을 삭제하지 마세요. 같은 프로필이면 정리 후 재빌드의 해시가 같아야 합니다. 보존할 릴리스는 아티팩트 저장소에 둡니다.
CLI 업그레이드는 별도 변경으로 진행합니다. 정확한 패키지 잠금이나 압축파일 체크섬을 갱신하고 깨끗한 출력 트리에서 재빌드한 뒤 카탈로그와 게임 결과를 비교하세요. 업그레이드를 위해 공개된 버전의 바이트를 교체하지 마세요. 각 전달물의 소스 커밋·도구 식별자·번들 해시를 기록해 보관 패키지를 고르거나 원래 환경에서 재빌드해 롤백할 수 있게 합니다.