게임

개발 문서

Zamgot 게임 개발 가이드 - 모든 게임 엔진 지원

엔진별 가이드:

실행 메모리 예산 / Runtime memory budgets

자산 경량화 기준·정적 점검 / Asset standards and static inspection

간편제작 엔진 2.7.6부터 제공하는 공통 기능입니다. 새 간편제작 프로젝트의 기본 판은 2.7.6이며 기존 프로젝트의 엔진 판은 유지됩니다. 2.7.5·2.7.2·2.6.0 등 이전 판도 선택할 수 있고 2.7.0은 목록에서 숨깁니다. 기기의 실행 메모리·추정 GPU 자원이 예산에 가까워지면 최근 가장 크게 늘어난 범주의 무거운 작업을 멈춥니다. 화면에는 멈춘 작업과 다음 행동을, 제작소 콘솔에는 범주·수치·작업명을 표시합니다.

예산은 플랫폼이 기기별로 정하고 실측에 따라 조정됩니다. 서버가 부팅 설정으로 내려주므로 지원 엔진을 처음 적용한 뒤에는 엔진 재발행 없이 바꿀 수 있습니다. 서버 설정이 없거나 잘못되면 휴대폰 384 / 192MiB, 태블릿 512 / 256MiB, PC 1536 / 768MiB(실행 메모리 / GPU 추정량)와 85% 입장 제한을 사용합니다. 게임 제작자는 예산을 올릴 수 없습니다. 이는 엔진 정책이며 iOS WebContent·운영체제의 실제 한도를 올리는 기능은 아닙니다.

모델 파일 크기보다 내부 이미지 해상도가 중요합니다. RGBA 이미지는 가로 × 세로 × 4바이트이며, 4096² 한 장은 64MiB입니다. 사용하는 모델·이미지만 불러오고, 필요 없는 재질·동작·변형은 제작 단계에서 제거하세요. 전체 정점 배열을 매 프레임 복사하지 말고 바뀐 구간만 처리하세요.

무거운 작업 시작 전에 zamgot.작업표시이름설정("장면 생성")을, 끝나면 zamgot.작업표시이름해제()를 호출할 수 있습니다. API가 false 또는 ()를 돌려주면 zamgot.자원마지막오류()와 메시 오류를 확인하고 반복 요청을 멈추세요. 메모리 보호 오류는 매 프레임 재시도하지 않습니다.

직전 실행 종료 안내는 지워지지 않은 실행 표식에 근거합니다. 메모리 종료를 확정하는 기록은 아닙니다. 일부 이미지 형식·브라우저 내부 메모리는 사전 측정할 수 없으므로 실기기 검증도 필요합니다. 작업명은 로컬 화면·콘솔·세션 기록에만 남고 서버에는 익명 수치·기기 종류·OS/브라우저 계열·직전 실행의 적용 예산·고정 범주만 전달됩니다. UA 원문·버전·개인/게임/프로젝트 식별자는 보내지 않습니다.

This common feature is available from engine 2.7.6. New Script projects default to 2.7.6; existing project engine pins are preserved. Older versions including 2.7.5, 2.7.2 and 2.6.0 remain selectable, while 2.7.0 stays hidden. Near the device's runtime/GPU estimate budget, the engine pauses heavy work in the fastest growing measured category. Players see what paused and what to do; the Studio console shows category, numbers and activity names.

The platform sets budgets for each physical device class and adjusts them from measurements. Budgets arrive in the boot config, so later adjustments do not require republishing a supporting engine. Missing or invalid server settings fall back to phone 384 / 192MiB, tablet 512 / 256MiB and PC 1536 / 768MiB (runtime / GPU estimate), with admission restricted at 85%. Creators cannot increase these budgets. This policy does not increase iOS WebContent or OS limits.

A decoded RGBA image needs width × height × 4 bytes: one 4096² image is 64MiB. Load only needed assets, trim unused materials/animations/variants, and process changed vertex ranges instead of copying every vertex each frame.

Optionally call zamgot.set_activity_name("Scene generation") before heavy work and zamgot.clear_activity_name() when done. On false or () check zamgot.resource_last_error() and the mesh error, then stop retrying. A leftover run marker indicates an unexpected ending; it does not establish OOM. Some formats and browser allocations remain unmeasured. Activity names stay local; server reports contain anonymous numbers, device class, OS/browser families, the previous run's applied budget and fixed categories. They exclude raw UA, versions and personal/game/project identifiers.

제작소 메모리 측정과 기기별 최적화 / Studio memory measurement and device optimization

Reviewed 2026-10-13. MB/GB are source units; engine charts use MiB.

DeviceReported quantitySource dateConfidence / scopeSource
iPhone / WebKit~1.5 GB2024-08-09WebKit engineer; variable soft thresholdsource
iPhone 17 Pro / iOS 26.3–26.4.1ActiveHard 2048 MB2026-04 (case report)Low: single-device-family report, not a platform guaranteesource
iPad / WebKitUnknown / 미확정2026-10-11 reviewNo universal hard maximum establishedsource
PC / Chrome wasm324 GiB addressability2020-05-14High for wasm32 addressing; not a safe process budgetsource
Android / Chrome (historical)~256–300 MB allocation issues2020-11-30 / 2021-02-15Low for current devices: historical firsthand reportssource / case
Safari / Unity WebGL practice300–500 MB target2023-10-03Medium: engine developer recommendation, not OS limitsource
iOS / PlayCanvas GPU practice300–350 MB risk range2022-12-28Low: developer observation of estimated VRAMsource
Engine policyWASM MiBGPU estimate MiB
phone384192
tablet512256
pc1536768

Admission ratio: 0.85; fallback policy only.

AI 기기 도구는 기능이 켜진 환경에서만 사용합니다. run_device_check는 즉시 runId를 반환하며 get_device_check(run_id)를 2초 이상 간격으로 조회해 running/done/failed를 확인합니다. done의 영수증을 검토한 뒤 지원 목록을 준비합니다.

웹에는 기기별로 보장된 단일 최대 메모리량이 없다. 위 수치는 단위도 서로 다르다. 출처의 MB/GB를 MiB/GiB로 바꾸어 같은 값으로 취급하지 않는다. 메모리 한도를 탐색하려고 큰 할당을 반복하지 않는다.

메모리 총량은 같은 시점의 실제 WASM 선형 메모리 크기 + 엔진 GPU 추정량이다. 프로세스 RSS 실측이 아니다. WASM에는 살아 있는 객체 외에 할당기·여유 페이지·고수위가 포함된다. CPU 범주 회계를 WASM에 다시 더하지 않는다. JS 힙과 UA 메모리는 WASM 등과 겹칠 수 있으므로 별도 표시하며 총량에 더하지 않는다.

WASM·GPU·JS·UA 각각의 구간 최대값과 동시에 관측된 총량 최대값은 다르다. 250ms 표본과 UA 비동기 조회는 순간 피크를 놓칠 수 있다. GPU는 엔진의 이미지·메시 추정 회계이며 드라이버·브라우저 내부·모든 렌더 타깃을 보증하지 않는다. 조회 불가 값은 0이 아닌 조회 불가로 읽는다. iOS 등 브라우저 API가 없으면 엔진 회계만 표시한다. 점검 결과는 부팅 피크·오류를 보존하되 표본 수·프레임 성능·관측 공백 판정은 지정한 측정 구간만 사용하며 구간 시작과 끝의 공백도 포함한다. 화면 시계열은 최근 200표본이고 최대값은 현재 미리보기 문서 구간이다.

JS 힙 performance.memory는 비표준 구현 정보다. measureUserAgentSpecificMemory는 지원 브라우저의 격리 조건에서만 선택적으로 사용한다. 지원 여부를 감지하고 실패해도 엔진 회계는 유지한다. 브라우저 API가 보고하는 범위·시점은 엔진 표본과 다르다.

기기 예산선은 현재 물리 기기와 모의 대상 기기 각각의 WASM·GPU 예산 및 85% 입장선이다. SiteSetting.runtimeMemoryBudget의 서버 부팅 정책이 정본이며 플랫폼이 변경할 수 있다. 없는/잘못된 설정에만 아래 기본값을 쓴다. 영수증에는 그 실행의 예산과 출처가 남는다. 프로젝트가 예산을 더 낮추면 서버 예산 일치 점검은 실패한다; 임의로 높일 수 없다.

대상 기기 선택은 새 V107 점검 스위치를 켠 제작소의 인라인 미리보기에서만 엔진의 기존 기기 감지 입력을 선택한다. 예산·휴대폰 그림 축소 및 해당 기기 정책을 적용하되 실제 Safari·GPU·RAM·OS 종료 한도·터치 성능은 재현하지 않는다. 기존 화면 기기 선택만으로 이 정책이 바뀌지는 않는다. 팝아웃·휴대폰 별도 세션과 라이브 실행은 먼저 종료한다.

run_device_check는 동기화한 현재 HEAD의 모든 파일 경로·크기·SHA256와 엔진·런타임 판을 정렬 해시로 묶고, 그 HEAD 바이트만 읽는 분석 미리보기를 10–60초 실행한다. steps는 기존 미리보기 시나리오 형식이다. 생략하면 유휴 실행 점검이며 게임 플레이 전체 통과를 뜻하지 않는다. 서로 다른 목표에서도 같은 중요한 장면·복원·정리 시나리오를 사용한다.

통과는 WASM·GPU 각 피크가 해당 예산의 admitRatio 이하, 3개/초 이상의 완전한 메모리 표본, 표본 공백 1.5초 이하, 평균 30FPS 이상·프레임 p95 33.34ms 이하·60프레임 이상·측정 시간의 80% 이상 프레임 관측·프레임 공백 1.5초 이하, 정책·런타임 판 일치, 보호/오류 없음, 시나리오 성공을 모두 요구한다. 부족한 데이터는 통과하지 않는다. GPU의 unknownFormats/unknownMeshes가 있거나 회계가 누락되면 통과하지 않는다. 프레임 판정은 엔진 프레임 시간과 실제 RAF 간격 중 큰 값을 쓰며 빠른 CPU 작업으로 느린 화면 갱신을 가리지 않는다.

영수증의 scope=simulated_engine_policy, hardwareVerified=false는 모의 정책 관측이라는 뜻이다. 브라우저가 제출한 관측으로 실제 기기 인증·변조 방지 벤치마크가 아니다. set_supported_devices(receipt_ids)는 같은 소스의 서버 저장 통과 영수증만 받아 목록 전체를 갱신한다(빈 배열은 비움). 수정·런타임 변경 후 다시 점검한다. 발행 manifest.json에 함께 고정되며 게임/라이브 판을 섞지 않는다. 공개 지원 목록은 기기 종류(phone/tablet/pc)이고 모델별 인증이 아니다. 대상 기기의 플랫폼 예산·입장 비율이 바뀌면 지원 목록을 다시 설정하기 전에 재점검한다. 사람 발행은 오래된 목록을 생략하고 계속할 수 있다. 이미 발행된 목록은 해당 판과 점검 당시 정책의 기록이다.

AI는 점검 → 범용 파일 수정 → 같은 시나리오 재점검 → 목록 설정까지 수행한다. 기기 도구는 발행을 호출하지 않는다. 사람은 기존 발행 버튼·승인과 배포 결정을 맡으며 기존 소유권·권한 확인을 유지한다. 목록에 없는 기기의 안내는 실행을 차단하지 않는다. 임의 네이티브 WASM에는 엔진 GPU/기기 정책 회계가 없어 점검은 명시적으로 실패하며 이를 지원 영수증으로 포장하지 않는다.

발행 시 오래되었거나 읽을 수 없는 지원 목록은 경고와 함께 빠지고 사람의 발행은 계속됩니다. 공개 manifest에는 기기 종류·영수증 ID·소스 SHA·정책 판·통과 여부만 실립니다. 그림 경로·오류·진단 전문은 비공개 R2 영수증에만 보관합니다.

iPhone / WebKit: WebContent 소프트 한도 설명. 여유 RAM·다른 탭·기기 RAM에 따라 낮아진다. 보장된 할당량이 아니며 초과 시 페이지가 종료·재로드될 수 있다.

iPhone 17 Pro / iOS 26.3–26.4.1: 개발자가 보고한 Jetsam 로그 사례. Apple 답변은 iPhone과 iPad의 정책 차이만 확인한다. 모든 iPhone의 상한으로 쓰지 않는다.

iPad / WebKit: iPhone 수치를 복사하지 않는다. 실기기별 점검이 필요하며 메모리 조회 API가 없으면 엔진 회계만 표시한다.

PC / Chrome wasm32: V8의 wasm32 선형 메모리 주소 범위. 브라우저 프로세스 전체 RAM·GPU·안전 예산이나 memory64의 상한은 아니다. 실제 할당은 더 작게 실패할 수 있다.

Android / Chrome (historical): 2020년 256MB 성장 문제와 2021년 약 300MB 초과 할당 불안정 보고. 32비트 주소 공간·분편화 등이 관련되며 최신 Android의 고정 상한으로 쓰지 않는다.

Safari / Unity WebGL practice: Unity 개발자의 경험상 목표 범위. 다른 엔진에 대한 보장이나 Safari의 공식 최대량이 아니다.

iOS / PlayCanvas GPU practice: 큰 모델 적재 중 GPU 메모리 위험 사례. 통합 메모리 기기의 실제 VRAM 상한으로 확정하지 않는다.

Device AI tools are available only when the feature is enabled. run_device_check returns a runId immediately; poll get_device_check(run_id) at intervals of at least two seconds for running/done/failed. Review the done receipt before preparing supported devices.

There is no guaranteed universal per-device maximum. Source MB/GB figures are not interchangeable with MiB/GiB. Do not probe browser limits by repeatedly allocating large buffers.

Engine memory total estimates simultaneous measured WASM linear-memory capacity plus estimated GPU usage. It is not process RSS. WASM includes allocator overhead, spare pages and its high-water mark. Do not add CPU categories to WASM again. JS heap and UA memory may overlap WASM and are displayed separately, never added to the total.

Per-component interval maxima differ from the maximum simultaneous total. Sampling every 250ms and asynchronous UA measurements can miss transient peaks. GPU accounting estimates engine images/meshes, excluding guaranteed coverage of driver/browser overhead or all render targets. Unavailable is not zero; browsers such as iOS show engine accounting only when browser APIs are missing. Checks retain boot peaks/errors, but sample counts, frame performance and coverage gates use only the requested interval, including leading and trailing gaps. The UI shows the last 200 samples; maxima belong to the current preview document.

performance.memory is nonstandard implementation information. measureUserAgentSpecificMemory is optional and requires browser support and isolation. Detect support; API failures must not erase engine accounting. API scope/timing differs from engine samples.

Budget lines show actual-device and simulated-target WASM/GPU budgets plus admission at 85%. The platform-controlled SiteSetting.runtimeMemoryBudget boot policy takes precedence over defaults below. Receipts preserve applied budgets and their source. Lower project budgets cause a policy mismatch during a server-budget check; creators cannot increase platform budgets.

The V107 opt-in inline Studio preview adapter selects existing engine device detection inputs. This applies engine budgets, phone texture downscaling and related device policy; it cannot reproduce real Safari, GPU, RAM, OS termination limits or touch performance. Existing viewport device selection alone does not do this. Close external/phone sessions and live playback first.

run_device_check hashes every synced HEAD path, byte size and SHA256 plus engine/runtime version, then runs an analysis preview reading only that captured HEAD for 10–60 seconds. steps use the existing preview scenario format. Omitting steps checks idle execution, not complete gameplay. Reuse important loading, restore and cleanup scenarios across targets.

Passing requires separate WASM/GPU peaks at or below budget × admitRatio, at least three complete memory samples per second, sample gaps at most 1.5 seconds, average at least 30FPS, frame p95 at most 33.34ms, at least 60 frames spanning 80% of the interval with gaps at most 1.5 seconds, matching policy/runtime, no protection/errors, and scenario success. Missing data never passes. Missing GPU accounting or unknownFormats/unknownMeshes also prevent passing. Frame gates use the greater of engine frame time and actual RAF interval; fast CPU work cannot hide slow display cadence.

scope=simulated_engine_policy and hardwareVerified=false describe browser-reported simulated-policy observations, not hardware certification or a tamper-proof benchmark. set_supported_devices(receipt_ids) replaces the whole list using only server-stored passed receipts for the identical source; [] clears it. Recheck after edits/runtime changes. The immutable publication manifest pins receipts to the game or live version. Device classes phone/tablet/pc are not certified hardware models. A changed target budget/admission ratio requires rechecking before support list updates. Human publication may continue with the stale list omitted. Already published lists record that version and the policy at check time.

AI checks, edits generic project files, rechecks and updates the list. Device tools never publish. Humans decide deployment through existing publication/approval controls; ownership and authorization remain required. Unlisted devices receive advice without a play block. Arbitrary native WASM lacks the engine GPU/policy contract and explicitly fails receipt qualification.

Stale or unreadable support is omitted with a warning while human publication continues. Public manifests contain only device class, receipt ID, source SHA, policy version and pass status. Asset paths, errors and full diagnostics remain in private R2 receipts.

iPhone / WebKit: A WebContent soft threshold varies with memory pressure, other tabs and device RAM. It is not a guaranteed allocation; termination or reload can occur.

iPhone 17 Pro / iOS 26.3–26.4.1: A developer-reported Jetsam log. Apple confirms different iPhone/iPad policies, not this number as a universal ceiling.

iPad / WebKit: Do not copy iPhone figures. Check actual hardware; display engine accounting only when browser memory APIs are unavailable.

PC / Chrome wasm32: V8 wasm32 linear-memory addressing capacity, not process RAM, GPU budget, safe allocation or a memory64 ceiling. Allocations can fail earlier.

Android / Chrome (historical): Historical growth/allocation failures around 256–300 MB, involving address-space fragmentation and 32-bit browsers. This is not a current Android hard cap.

Safari / Unity WebGL practice: An experienced Unity developer target, not an official Safari ceiling or a guarantee for other engines.

iOS / PlayCanvas GPU practice: A developer observation during large-model loading, not an established physical VRAM ceiling on unified-memory devices.

압축 크기와 디코드 픽셀 / Compressed bytes versus decoded pixels

압축 PNG/JPEG/GLB 용량으로 실행 메모리를 계산하지 않는다. RGBA8 기본 레벨은 가로×세로×4: 4096²=64MiB, 2048²=16MiB이며 밉·레이어·사본은 별도다. 가장 큰 그림 목록의 rgbaBytes는 이 RGBA8 환산 예시이며 실제 GPU 형식·압축·부동소수점 형식의 사용량과 같지 않다. 크기·GPU 추정·범주 증가를 함께 확인하고 원본을 필요한 해상도로 만든다. 적절한 GPU 압축은 지원 형식과 품질을 확인한 뒤 쓴다. 휴대폰 자동 축소는 2.7.6의 [performance] mobile_texture_downscale=true, mobile_texture_max_size=2048(256..2048)이며 false로 끌 수 있다. 원본 디코드 순간 비용과 UI·nearest·픽셀 좌표·압축 컨테이너 등의 제외 규칙은 #mobile-texture-downscale을 읽는다.

Do not estimate runtime RAM from PNG/JPEG/GLB download size. Base-level RGBA8 is width × height × 4: 4096²=64MiB, 2048²=16MiB; add mips, layers and copies separately. Largest-image rgbaBytes is this hypothetical RGBA8 equivalent, not actual usage for compressed or floating-point GPU formats. Inspect dimensions, GPU estimates and category growth together. Author suitably sized sources and choose supported GPU compression with acceptable quality. Engine 2.7.6 uses [performance] mobile_texture_downscale=true and mobile_texture_max_size=2048 (256..2048); false opts out. Read #mobile-texture-downscale for transient original-decode costs and exclusions.

CPU와 GPU 사본 / CPU and GPU copies

CPU 픽셀과 GPU 텍스처를 함께 유지하면 중복 비용이 생긴다. 2.7.6은 일반 모델·외부 그림 업로드 후 CPU 픽셀을 해제한다. 픽셀 편집 등 실제로 필요한 보관은 예외다. 이미 해제하는 경로를 다시 복제하지 말고 범주 회계로 확인한다. 해제 후 WASM 선형 메모리는 줄지 않을 수 있으며 고수위와 살아 있는 객체를 구별한다.

Retaining decoded CPU pixels and GPU textures duplicates storage. Engine 2.7.6 releases ordinary model/external-image CPU pixels after upload, except required editing paths. Avoid creating new copies; inspect categories. WASM capacity may stay high after objects are freed, so distinguish capacity from live ownership.

숨긴 후보와 무제한 풀 / Hidden candidates and unbounded pools

숨김은 해제가 아니다. 보이지 않는 변형·후보를 처음부터 전부 불러오지 말고 보이는 것만 적재한다. 휴대폰에는 미리 구운 단일 모델과 작은 텍스처를 우선한다. 풀에 보유할 모델/캐릭터 수를 제한하고 사용이 끝난 초과 항목은 실제 destroy로 해제한다. 모델 수 증가는 숨김·풀의 소유권을 확정하지 않으므로 AI가 관련 코드를 읽고 검증한다.

Hidden does not mean freed. Load visible assets on demand instead of preloading every variant/candidate. Prefer a baked single model and smaller textures on phones. Bound pools and destroy excess objects when finished. Rising model counts only suggest hidden/pool ownership; inspect code before attributing cause.

전체 정점과 큰 JSON 왕복 / Whole-vertex copies and large JSON round trips

메시 편집 API로 매 프레임 전체 정점 배열을 읽거나 큰 JSON 맵을 WASM↔JS로 왕복시키면 임시 메모리·복사 비용이 커진다. 필요한 정점 구간만 읽고 바뀐 범위만 갱신하며 안정적인 값을 재사용한다. 범주 증가와 프레임 p95를 함께 비교한다. 내부 수치만으로 API 호출 횟수를 확정하지 않는다.

Reading all mesh vertices every frame or round-tripping large JSON maps creates temporary buffers and copies. Read only required vertex ranges, update changed ranges, and reuse stable values. Compare mesh-category growth with frame p95; counters alone do not establish API-call counts.

한꺼번에 복원하는 큰 작업 / Bulk restoration spikes

저장 데이터 복원·장면 생성·후보 생성이 한 프레임에 몰리지 않게 작업 큐를 만들고 여러 프레임으로 나눠 처리한다. 사용 가능한 예산을 확인한 뒤 작은 묶음으로 처리한다. 프레임 지연은 복원 원인의 확정이 아니므로 시나리오 시점과 코드를 대조한다.

Queue save restoration, scene creation and candidate generation in small batches across frames. Check remaining budget before admitting work. Frame delays suggest a spike, not proof of a restoration cause; compare scenario timing and code.

동시 디코드와 적재 / Concurrent decoding and loading

한 파일 크기가 작아도 원본·디코드 결과·축소본·업로드가 동시에 겹치면 피크가 커진다. 동시 적재 수를 제한하고 후보는 수요가 생길 때 순차 적재한다. assetDecodeLeaseCount 피크와 model_loading/textures 증가를 비교한다. 진행 중 작업을 취소한 뒤 실제 자원 해제 여부도 점검한다.

Original bytes, decoded pixels, reduced pixels and uploads can overlap even for small files. Limit concurrent loads and load candidates on demand. Compare assetDecodeLeaseCount peaks with model_loading/textures growth; verify cancellation also releases resources.

AI 점검 순서 / AI checklist

  1. 성능 패널의 메모리 총량·WASM/GPU 개별 피크·범주별 증가를 읽고 현재/대상 예산선과 비교한다.
  2. 가장 큰 그림 목록의 해상도·디코드 RGBA·CPU/GPU 추정치를 확인한다.
  3. 보호 범주·오류 E_RESOURCE_MEMORY_BUDGET / E_RESOURCE_MEMORY_MONITOR / E_RESOURCE_SCRIPT_BUDGET을 확인하고 매 프레임 재시도를 멈춘다.
  4. 다음 로드의 종료 흔적을 확인한다. 예상 밖 종료 표식은 OOM의 확정 증거가 아니다.
  5. 기능이 켜진 환경에서만 대상 기기의 중요한 적재·복원·정리 시나리오로 run_device_check를 시작하고 get_device_check(run_id)로 결과를 조회한다.
  6. 관측/추정 원인을 구분해 관련 가이드 절과 코드를 읽고 범용 최적화를 수정한다.
  7. 같은 소스의 나머지 대상에도 같은 시나리오로 다시 점검한다. 최종 수정 후 모든 지원 영수증을 새로 얻는다.
  8. set_supported_devices에 최종 소스의 통과 영수증 ID만 넣고 사람의 발행·승인을 기다린다.
  1. Read engine total, separate WASM/GPU peaks and category growth against actual/target budget lines.
  2. Inspect largest images: resolution, decoded RGBA and CPU/GPU estimates.
  3. Check protection category and E_RESOURCE_MEMORY_BUDGET / E_RESOURCE_MEMORY_MONITOR / E_RESOURCE_SCRIPT_BUDGET; stop per-frame retries.
  4. Inspect the previous-run breadcrumb on the next load. Unexpected termination is not proof of OOM.
  5. Only when enabled, start run_device_check with important loading, restoration and cleanup scenarios, then poll get_device_check(run_id) for the result.
  6. Separate observations from suspected causes; read linked guide sections and code, then make generic optimizations.
  7. Repeat the same scenarios on all remaining targets. After the final edit obtain new receipts for every supported target.
  8. Pass only final-source passed receipt IDs to set_supported_devices and await human publication/approval.

Memory API reference / Memory API reference

자산 경량화 기준 / Asset optimization standards

휴대폰 텍스처는 1024–2048을 권장하고 4096은 피한다. PC도 보통 2048을 사용하고 가까이 보는 자산만 4096을 검토한다. 화면용 RGBA8 크기 = 가로×세로×4바이트, 밉맵 포함 근사 = ×4/3(약 1.33배). 1024²=4MiB(밉맵 5.33), 2048²=16MiB(21.33), 4096²=64MiB(85.33). 1MiB=1,048,576바이트. 파일 다운로드 크기와 화면 메모리는 별개다. 얇고 긴 텍스처는 밉맵 증가율이 1.33배보다 클 수 있어 점검기는 실제 단계별 합과 1.33 근사 중 큰 값을 사용한다.

한 장면 텍스처 목표: 휴대폰 128MiB, PC 512MiB(밉맵 포함 보수적 환산). 기존 엔진 GPU 예산 192/768MiB의 2/3만 텍스처에 쓰고 나머지는 메시·렌더 타깃·후처리에 남기는 플랫폼 설계값이며 OS 상한이 아니다. 총 게임 메모리 300–500MB 권고와 iPhone 약 1.5GB 소프트/약 2GB 종료 사례도 아래 출처의 경험·사례일 뿐 보장 한도가 아니다. PC 목표는 폴백 GPU 예산에 근거한 설계값이며 실기기에서 확인한다.

캐릭터는 화면에 필요한 부품과 착장만 불러온다. 기본 착장은 미리 한 모델로 굽고, 겹쳐 가려지는 몸·머리·옷 메시와 GLB 가림 변형의 중복 텍스처를 제거한다. 단순히 부품을 병합해도 텍스처를 재사용·정리하지 않으면 메모리가 줄지 않는다. 교체 전용 변형은 필요할 때 불러오고 기존 자원을 해제한다. 장면에 없는 변형/숨긴 풀도 메모리를 차지할 수 있다.

작은 이미지가 많으면 재질별 아틀라스로 묶고 패딩·UV·밉맵 번짐을 확인한다. 거대한 4096 아틀라스 하나로 합치는 것은 경량화가 아니다. 모델당 이미지 권고 상한은 휴대폰 8개/PC 16개, 모델 하나의 밉맵 포함 텍스처 목표는 32/128MiB다. 해상도·합계 예산을 먼저 맞춘 뒤 개수와 드로우 콜을 줄인다.

PNG는 알파/정밀 데이터, JPEG·WebP는 불투명 색상/다운로드 축소에 사용한다. 디스크 압축률은 RGBA 메모리를 줄이지 않는다. KTX2/Basis GPU 압축은 런타임·확장·트랜스코더 지원을 확인한 뒤에만 사용한다. 현재 간편제작 엔진은 KHR_texture_basisu GLB를 지원한다고 가정하지 않는다. 점검기는 KTX2의 vkFormat·typeSize로 계산한다. RGBA8/16F/32F는 텍셀당 4/8/16바이트이며 면·레이어·깊이를 곱한다. BCn/ASTC는 블록 크기로 계산하고 형식을 모르면 미확인이다. 지원 확인 경고는 GLB의 KHR_texture_basisu와 BCn/ASTC에만 낸다. 간편제작 skybox·environment_map·환경 프로브용 비압축 KTX2 큐브맵은 지원 경고 대상이 아니다. Draco/meshopt도 압축·로더 지원과 디코드 비용을 확인한다.

모델 다운로드 권고: 파일 하나 휴대폰 10MiB/PC 25MiB 이하. 오디오 한 파일 2MiB/5MiB 이하, 효과음은 짧게·모노·불필요한 무음 제거, 음악은 지원 코덱(Ogg/MP3 등)을 실기기에서 확인한다. WAV PCM 디코드 메모리는 초×샘플률×채널×샘플 바이트이며 압축 오디오는 재생 시 더 커질 수 있다. 이 크기/개수 기준은 네트워크·디코드 비용을 줄이기 위한 플랫폼 권고값이다.

엔진 메모리 관문 경고 배너는 현재 회계와 새 자원 예약이 기기 예산/입장선에 가까워져 작업을 보호 중단했다는 뜻이다. 제작소 정적 경고는 엔진 관문을 바꾸지 않는다. 큰 텍스처부터 낮추고 변형·동시 부품·숨긴 풀·오디오를 줄인 뒤 다시 측정한다. 배너를 숨기거나 예산·축소 보호를 끄는 처방을 하지 않는다. 원본 4096 디코드의 일시 메모리도 있으므로 런타임 자동 축소에만 기대지 않는다.

AI와 제작자는 배포 전 audit_assets(target:"phone")와 audit_assets(target:"pc")를 실행해 경고 목록과 rows 표를 확인한다. paths 배열은 함께 쓰는 장면 자산 후보만 지정할 수 있다. 프로젝트 전수 합은 장면 동시 로딩 실측이 아니며 외부 이미지 경로는 합계에서 중복 제외한다. GLB 내장 PNG/JPEG/WebP/KTX2 헤더·이미지 개수·RGBA/밉맵 추정만 읽고 디코드/자산 수정은 하지 않는다. 독립 이미지와 GLB 외부 이미지는 최대 64KiB 헤더만 읽고 .gltf·.obj·.fbx는 본문을 읽지 않고 미확인으로 남긴다. JPEG 헤더가 범위 안에 없으면 미확인이다. GLB 본문 64MiB 초과·읽기 실패·미지원 헤더/모델·외부 URL·전체 읽기 256MiB/2000파일/25초 제한은 미확인 경고, 누락을 0이나 통과로 읽지 않는다.

점검은 기본 경고 전용으로 배포를 막지 않는다. 대표 기준 변경 시 이 정본 assetBudget.enforcement만 block으로 바꾸면 제작소 배포 준비를 차단한다(서버 발행 권한/엔진 관문을 바꾸는 정책은 별도). AI 응답에는 policyVersion·target·complete·scope·sceneMeasured:false·totals·rows·warnings·warningCount·truncated·blocksDeployment가 있다. 열린 제작소 탭이 실행 주체이고 간편제작은 브라우저 로컬/서버 파일을 읽는다. 근본제작의 데몬 디스크 점검·데몬 AI 공통 탭 브리지는 데몬 0.36.192 이상과 audit-list/audit-read·헤더 읽기 지원 확인 뒤에만 가능하다. 미지원이면 “점검하려면 데몬 업데이트가 필요합니다”를 안내한다. 서버 MCP도 같은 탭 브리지로 조회하며 독립 stdio/탭 없음은 명시 오류다. 수정 뒤 최종 소스로 재점검하고 기기 점검 기능이 켜져 있으면 run_device_check/get_device_check로 부팅·교체·밀집 장면을 측정한다.

점검 결과는 최대 1000행·경고 200개·자산별 이미지 상세 32개로 제한되며 truncated를 확인한다. 더 자세한 조회는 paths로 나눈다. PNG/JPEG/WebP 헤더 계산은 RGBA8 후보 추정, KTX2는 알려진 포맷의 텍셀/블록 바이트 추정이며 보장 상한이 아니다. 밉맵은 전체 단계 합과 4/3 근사 중 큰 값을 사용한다. 실제 GPU 포맷·밉맵 생성·sampler/색 공간별 복제·동적 로딩·임시 버퍼는 실행 중 측정으로 확인한다. 점검은 현재 파일을 읽는 자문이며 불변 소스 인증서가 아니다. 예산을 늘려 통과시키지 않는다. 근본제작은 기존 데몬 파일 목록의 가시 영역(숨김/빌드 폴더 제외)을 점검하며 파일 목록 API가 보고하지 않는 누락은 판별할 수 없다.

For phones, prefer 1024–2048 textures and avoid 4096. PCs should normally use 2048; reserve 4096 for close views. RGBA8 screen memory = width × height × 4 bytes; with mipmaps use ×4/3 (about 1.33). 1024² = 4MiB (5.33 with mips), 2048² = 16MiB (21.33), 4096² = 64MiB (85.33). MiB = 1,048,576 bytes. Download size is not decoded memory. Thin textures can exceed the 1.33 mip factor; inspection uses the larger of the full mip-chain sum and that approximation.

Scene texture targets including conservative mip estimates: phone 128MiB, PC 512MiB. These platform design targets allocate two thirds of the existing 192/768MiB GPU budgets, leaving room for meshes, render targets and post-processing. They are not OS limits. The 300–500MB total game recommendation and iPhone roughly 1.5GB soft/2GB termination reports below are guidance and cases, not guaranteed allocations; confirm on hardware.

Load only visible character parts and outfits. Bake the default outfit, remove hidden body/hair/clothing meshes and duplicate textures in occlusion variants. Merging parts alone does not save texture memory. Load replacement variants on demand and release old resources; hidden pools can still retain memory.

Atlas small images by material with padding and UV/mipmap checks. A giant 4096 atlas does not guarantee savings. Prefer at most 8 images per model on phones and 16 on PCs, with model texture targets of 32/128MiB including mips. Meet resolution and memory budgets before reducing image count or draw calls.

Use PNG for alpha or precise data, JPEG/WebP to reduce opaque color downloads. File compression does not reduce RGBA memory. KTX2/Basis GPU compression requires proven runtime, extension and transcoder support; do not assume KHR_texture_basisu GLB support in the current scripted runtime. Inspection reads KTX2 vkFormat/typeSize: RGBA8/16F/32F use 4/8/16 bytes per texel times faces, layers and depth; BCn/ASTC use block sizes. Unknown formats stay unverified. Support warnings apply only to KHR_texture_basisu in GLB and BCn/ASTC. Uncompressed KTX2 cubemaps for skybox, environment_map and environment probes require no support warning. Verify Draco/meshopt loader support and decode cost too.

Recommended download size per model: phone 10MiB, PC 25MiB; per audio file: 2/5MiB. Keep effects short, mono where suitable and remove silence. Verify music codecs such as Ogg/MP3 on hardware. PCM memory = seconds × sample rate × channels × bytes per sample; compressed audio may grow when decoded. File and count limits are platform recommendations for download and decode cost.

The engine memory banner means current accounting plus resource reservations approach the device budget/admission threshold and work was stopped for protection. Static inspection does not change the runtime gate. Reduce large textures, variants, simultaneous parts, hidden pools and audio; then measure again. Do not hide the banner or disable safety budgets/downscaling. Original 4096 decoding still needs temporary memory even with runtime downscaling.

Before publishing, call audit_assets(target:"phone") and audit_assets(target:"pc") and inspect rows and warnings. Optional paths selects candidate assets used together. Inventory sums are not measured scene residency; external image paths are deduplicated. GLB image headers (PNG/JPEG/WebP/KTX2), counts and RGBA/mipmap estimates require no decoding or edits. Standalone and external GLB images read at most 64KiB of headers; .gltf/.obj/.fbx are marked unverified without reading their bodies. JPEG dimensions beyond the prefix remain unverified. Unsupported headers/models, external URLs, read failure or limits (64MiB/GLB, 256MiB read total, 2000 files, 25 seconds) produce incomplete warnings, never a zero-memory pass.

The default policy warns and permits deployment. Changing only assetBudget.enforcement to block stops Studio deployment preparation; server publishing authority and runtime protection remain separate policies. Responses include policyVersion, target, complete, scope, sceneMeasured:false, totals, rows, warnings, warningCount, truncated and blocksDeployment. An open Studio tab executes requests from browser-local/server files for scripted projects. Native disk inspection and the daemon AI tab bridge require daemon 0.36.192 or later plus confirmed audit-list/audit-read and header-read support. Unsupported daemons show an update-required message. Server MCP uses this tab bridge; standalone stdio or absent tabs report explicit errors. Recheck final edits and, if device tools are enabled, measure boot, replacements and crowded scenes with run_device_check/get_device_check.

Results are capped at 1000 rows, 200 warnings and 32 image details per asset; check truncated and split requests with paths. PNG/JPEG/WebP use RGBA8 planning estimates and KTX2 uses known texel/block formats, not a guaranteed upper bound. Mips use the larger of the full chain and a 4/3 approximation; actual GPU formats, mip generation, sampler/color-space copies, dynamic loads and temporary buffers require runtime measurement. Inspection reads current files and is advice, not an immutable source certificate. Do not raise budgets merely to pass. Native projects inspect the visible inventory from the existing daemon API, which excludes hidden/build folders; omissions not reported by that API cannot be detected.

RGBA8 texel bytes / Mipmaps approximately one third extra / glTF 2.0 / GLB format

휴대폰 텍스처 자동 축소 / Automatic phone texture downscaling

간편제작 엔진 2.7.6부터 모든 게임에 기본 적용합니다. 실제 휴대폰에서 긴 변이 2048픽셀을 넘는 일반 이미지를 비율 유지 축소합니다. PC·태블릿은 원본을 유지하며 제작소의 가상 기기 선택은 이 판정을 바꾸지 않습니다. GLB 내장 이미지, 외부 PNG/JPEG/WebP, 일반 스프라이트에 같은 규칙이 적용됩니다. SVG는 목표 크기로 직접 래스터화합니다.

4096×4096 RGBA 한 장은 64MiB → 2048×2048 16MiB, 세 장은 192MiB → 48MiB입니다. 디코드·업로드 픽셀의 예이며 파일 크기나 전체 실행 메모리가 아닙니다. 확대하면 세부 무늬·작은 글자가 흐려질 수 있습니다. 최선은 원본을 처음부터 필요한 해상도로 제작하는 것입니다.

모델·외부 이미지 텍스처는 GPU 업로드가 끝나면 CPU 픽셀 사본을 해제합니다. 픽셀 읽기·수정 API를 구현하는 경로는 로드 때 CPU 사본을 유지해야 합니다(현재 스크립트에는 픽셀 읽기 API가 없습니다). 메시 편집용 데이터와 생성 글꼴 아틀라스는 유지합니다. GPU 저장량과 WASM 메모리 고수위는 이 해제로 줄어드는 값이 아닙니다.

제작소 프로젝트 설정에서 켜고 끄거나 zamgot.toml에 아래 설정을 씁니다. 기본값은 true·2048, 상한은 정수 256~2048입니다. false는 원본을 보존하지만 메모리 예산 보호는 유지됩니다. 큰 원본을 많이 로드하면 예산 알림으로 작업이 멈추거나 브라우저·운영체제가 실행을 종료할 수 있습니다. 변경 후 미리보기를 다시 시작하고, 공개 게임에는 새 판을 발행해 반영하세요.

[performance]
mobile_texture_downscale = true # 원본 보존은 false
mobile_texture_max_size = 2048 # 256..2048 정수

픽셀아트([game] pixel_art=true)와 nearest 샘플링은 제외합니다. ui·fonts·pixel_art·atlases 폴더의 외부 이미지, Sprite.region·nine_slice처럼 픽셀 좌표를 쓰는 스프라이트는 원본을 유지합니다. 엔진이 생성하는 글꼴 아틀라스와 렌더 타깃, 배열·큐브 레이아웃 이미지, KTX2/Basis/DDS 압축 컨테이너·내장 밉맵도 이 축소 대상에서 제외합니다. 일반 모델의 정규화 UV는 유지됩니다.

정밀 이미지가 필요하면 fullres://assets/detail.png 경로도 사용할 수 있습니다. 같은 파일을 일반 경로와 fullres 경로로 함께 로드하면 별도 이미지가 생기므로 하나의 경로를 일관되게 쓰세요. GLB 안의 UI·글자 이미지는 폴더로 구별할 수 없으므로 nearest 샘플러 또는 프로젝트 설정으로 보호하세요.

zamgot.휴대폰텍스처정책() / zamgot.mobile_texture_policy()는 enabled·applied·max_size·physical_device·reason 맵을 읽기 전용으로 반환합니다. 제작소 콘솔과 __zamgot2_resources에는 정책·축소 건수·절약 바이트가 표시됩니다. 일반 이미지 디코더는 원본 한 장의 순간 메모리가 여전히 필요하며 엔진은 원본+축소 결과를 먼저 예약합니다. 축소가 모든 종료를 방지하는 것은 아닙니다.

Engine 2.7.6 enables this for every Script game by default. On physical phones, ordinary images with a longest edge above 2048 pixels are reduced proportionally. PCs and tablets retain originals; Studio device emulation does not change this policy. Embedded GLB images, external PNG/JPEG/WebP and ordinary sprites share the rule. SVG is rasterized directly at the target size.

One 4096×4096 RGBA image: 64MiB → 2048×2048 16MiB; three: 192MiB → 48MiB. This describes decoded/upload pixels, excluding file size, mip overhead and total process memory. Fine detail and small text may soften when enlarged. Prefer suitably sized source assets.

Model and external image textures release their CPU pixel copy after GPU upload. A pixel read/edit API must request CPU retention when loading (the current script API has no pixel reader). Mesh editing data and generated font atlases stay available. This release does not reduce GPU storage or the WASM memory high-water mark.

Use Studio project settings or the TOML below. Defaults are true and 2048; the maximum edge accepts integers from 256 to 2048. Set false to retain originals. Memory budget checks remain active: large originals can pause work or lead to browser/OS termination. Restart preview after changes and publish a new game version for public players.

[performance]
mobile_texture_downscale = true # false keeps originals
mobile_texture_max_size = 2048 # integer 256..2048

Exemptions: [game] pixel_art=true, nearest sampling, external paths with ui/fonts/pixel_art/atlases folder components, pixel-coordinate Sprite.region/nine_slice, generated font atlases/render targets, array/cubemap layouts, and KTX2/Basis/DDS containers including existing mips. Normalized model UVs stay valid. Embedded UI/text images need a nearest sampler or the project toggle because they have no external folder identity.

Use fullres://assets/detail.png for another precision image. Choose a consistent path: loading the same file through normal and fullres identities creates separate image assets. Read-only zamgot.mobile_texture_policy() / zamgot.휴대폰텍스처정책() returns enabled, applied, max_size, physical_device and reason. The Studio console and __zamgot2_resources expose the policy, downscaled count and saved bytes. A raster decoder still needs one original image temporarily; source plus output is admitted before decoding. This cannot guarantee protection from every memory termination.