ZEPETO 마네킹
ZEPETO 마네킹은 옷을 입어보거나 판매할 수 있는 기능을 지원하는 마네킹 API 패키지입니다.
- 당신이 만든 의류 아이템을 월드에서 판매할 수 있습니다.
- ZEPETO 캐릭터 NPC의 지정된 의상을 입은 마네킹을 만들 수 있습니다.
- 마네킹이나 물체와 상호작용하여 의류 아이템을 구매할 수 있습니다.
1단계 : 설치
창 → 패키지 관리자 → ZEPETO.World 패키지 1.21.15 이상을 먼저 설치하세요.
그 후, ZEPETO.Module 1.0.8 패키지를 설치하세요.

❗️ 주의
- 성능 개선의 일환으로, 독립형 패키지가 ZEPETO.Module 1.0.8 및 이후 버전 패키지에 통합되었습니다.
- 이전에 설치된 ZEPETO.Mannequin 패키지를 삭제하세요.
- 기존 패키지를 제거한 후, ZEPETO.Module 패키지 버전 1.0.8 이상을 설치하세요.
2단계 : 마네킹에 설정할 아이템 ID 확인
👍 아이템 ID 확인 방법
📘 아이템을 처음 만드는 경우, 다음 가이드를 참조하세요. [아이템 만들기]
3단계 : 마네킹 설정하기
마네킹 객체는 총 세 가지 방법으로 제작할 수 있습니다.
- 당신이 만든 아이템만 ZEPETO 마네킹으로 설정하고 판매할 수 있습니다.
- 검토에서 거부된 아이템은 판매할 수 없습니다.
- 따라서 이 기능을 사용하려면 Unity에 로그인해야 합니다.
- 마네킹 기능이 포함된 패키지를 게시할 때는 편집자로 로그인해야 합니다.
- ZEPETO 템플릿과 ZEPETO 모델 유형 마네킹을 사용할 때 소비되는 자원은 들어오는 ZEPETO 캐릭터 수에 해당하며, 이는 최적화에 영향을 미칠 수 있습니다.
3단계-1 : 간단한 유형

가장 기본적인 것입니다. 특정 객체는 마네킹 자식으로 추가하여 외관을 설정할 수 있습니다.
1) 상호작용할 객체를 추가합니다.
2) 객체와 상호작용하기 위해서는 충돌체를 추가해야 합니다.
- isTrigger를 체크해야 합니다. 체크하지 않으면 자동으로 트리거로 인식되도록 처리됩니다.
- 충돌체를 추가하지 않고 마네킹 컴포넌트를 추가하려고 하면 아래와 같은 경고 창이 나타납니다.

3) 물체에 마네킹 구성 요소를 추가하십시오.
4) 검사기에서 다음을 설정하십시오.
- 아이콘: 기본적으로 행거 아이콘이 표시됩니다. 사용자 정의 아이콘으로 변경할 수 있습니다.
- 아이콘 위치: 없으면 기본적으로 마네킹 구성 요소와 함께 물체 위치에 아이콘이 나타납니다.
- 원하는 위치에 나타나도록 위치 객체를 추가한 후 값을 입력하십시오.
- ids: 판매하고자 하는 의류 항목의 아이템 ID를 입력하십시오.

5) 빈 객체를 추가하고 객체 이름을 MannequinScript로 작성하십시오.
6) ZEPETO 추가 > Typescript를 선택하고 스크립트 이름을 MannequinScript로 작성하세요.
7) 아래와 같이 작성하세요.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { ZepetoPlayers, SpawnInfo } from 'ZEPETO.Character.Controller';
import { WorldService } from 'ZEPETO.World';
import { ItemContentsRequest, Mannequin, MannequinComponent, MannequinInteractable, MannequinPreviewer } from 'ZEPETO.Mannequin';
import { Object } from 'UnityEngine';
export default class MannequinScript extends ZepetoScriptBehaviour {
private _previewer: MannequinPreviewer;
Start() {
// 로그인한 ID를 기반으로 ZEPETO 캐릭터를 생성하는 코드
// ZepetoPlayers.instance.CreatePlayerWithUserId(WorldService.userId, SpawnInfo.Default, true);
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
const character = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// Mannequin Interactable Component 추가
character.gameObject.AddComponent<MannequinInteractable>();
});
// 모든 Mannequin 컴포넌트 찾기
const mannequins = Object.FindObjectsOfType<MannequinComponent>();
mannequins.forEach(m => {
// Collider에 들어가기
m.onActive.AddListener(contents => {
Mannequin.OpenUI(contents);
const zepetoContext = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character.Context;
this._previewer = new MannequinPreviewer(zepetoContext, contents);
this._previewer.PreviewContents();
});
// Collider에서 나가기
m.onCancel.AddListener(() => {
Mannequin.CloseUI();
this._previewer?.ResetContents();
});
});
}
}8) 객체에 스크립트를 추가한 후 [▶︎(재생)] 버튼을 눌러 실행하세요.

STEP 3-2 : ZEPETO 모델 유형

ZEPETO 캐릭터 NPC에 아이템 ID를 추가하여 마네킹의 외관을 설정할 수 있습니다.
1) 빈 오브젝트를 생성하고 이름을 마네킹으로 지정합니다.
2) 오브젝트와 상호작용하기 위해서는 콜라이더를 추가해야 합니다.
- isTrigger를 체크해야 합니다. 체크하지 않으면 자동으로 트리거로 인식됩니다.
3) 오브젝트에 마네킹 구성 요소를 추가합니다.
4) 인스펙터에서 다음을 설정해 주세요.
- 아이콘: 기본적으로 행거 아이콘이 표시됩니다. 사용자 정의 아이콘으로 변경할 수 있습니다.
- 아이콘 위치: 없으면 기본적으로 마네킹 구성 요소와 함께 오브젝트 위치에 아이콘이 나타납니다.
- 원하는 위치에 나타나도록 위치 오브젝트를 추가한 후 값을 입력합니다.
- ids: 판매하고자 하는 의류 아이템의 ID를 입력해 주세요.
- 포즈: 포즈를 선택하고 설정할 수 있습니다.
- 앞으로 원하는 포즈를 포즈 ID 형태로 제공할 예정입니다.

👍 장면에 이미 마네킹 스크립트가 있는 경우, 이후 단계를 건너뛸 수 있습니다.
5) 빈 오브젝트를 추가하고 오브젝트 이름을 MannequinScript로 작성합니다.
6) ZEPETO > Typescript를 추가하고 스크립트 이름을 MannequinScript로 작성합니다.
7) 아래와 같이 작성합니다.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { ZepetoPlayers, SpawnInfo } from 'ZEPETO.Character.Controller';
import { WorldService } from 'ZEPETO.World';
import { ItemContentsRequest, Mannequin, MannequinComponent, MannequinInteractable, MannequinPreviewer } from 'ZEPETO.Mannequin';
import { Object } from 'UnityEngine';
export default class MannequinScript extends ZepetoScriptBehaviour {
private _previewer: MannequinPreviewer;
Start() {
// 로그인한 ID를 기반으로 ZEPETO 캐릭터를 생성하는 코드
// ZepetoPlayers.instance.CreatePlayerWithUserId(WorldService.userId, SpawnInfo.Default, true);
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
const character = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// 마네킹 상호작용 컴포넌트 추가
character.gameObject.AddComponent<MannequinInteractable>();
});
// 모든 마네킹 컴포넌트 찾기
const mannequins = Object.FindObjectsOfType<MannequinComponent>();
mannequins.forEach(m => {
// 충돌체에 들어가기
m.onActive.AddListener(contents => {
Mannequin.OpenUI(contents);
const zepetoContext = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character.Context;
this._previewer = new MannequinPreviewer(zepetoContext, contents);
this._previewer.PreviewContents();
});
// 충돌체에서 나가기
m.onCancel.AddListener(() => {
Mannequin.CloseUI();
this._previewer?.ResetContents();
});
});
}
}8) 객체에 스크립트를 추가한 후 [▶︎(재생)] 버튼을 눌러 실행합니다.

3단계-3 : ZEPETO 템플릿 유형

ZEPETO ID를 입력하면 해당 사람이 입고 있는 옷이 마네킹으로 나타납니다. 그러나 당신이 만든 옷이 아니라면 옷이 표시되지 않습니다.
1) 빈 객체를 만들고 이름을 마네킹으로 지정합니다.
2) Collider는 객체와 상호작용하기 위해 추가되어야 합니다.
- isTrigger를 체크해야 합니다. 체크하지 않으면 자동으로 트리거로 인식됩니다.
3) 객체에 마네킹 구성 요소를 추가하세요.
4) 인스펙터에서 다음을 설정해 주세요.
- 아이콘: 기본적으로 행거 아이콘이 표시됩니다. 사용자 정의 아이콘으로 변경할 수 있습니다.
- 아이콘 위치: 없으면 기본적으로 마네킹 구성 요소와 함께 객체 위치에 아이콘이 나타납니다.
- 원하는 위치에 나타나도록 위치 객체를 추가한 후 값을 입력하세요.
- zepeto id: ZEPETO id를 입력해 주세요.
- 포즈: 포즈를 선택하고 설정할 수 있습니다.
- 앞으로 원하는 포즈를 포즈 id 형태로 제공할 예정입니다.

👍 이미 장면에 마네킹 스크립트가 있는 경우, 이후 단계를 건너뛸 수 있습니다.
5) 빈 객체를 추가하고 객체 이름을 MannequinScript로 작성하세요.
6) ZEPETO를 추가하고 스크립트 이름을 MannequinScript로 작성하세요.
7) 아래와 같이 작성하세요.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { ZepetoPlayers, SpawnInfo } from 'ZEPETO.Character.Controller';
import { WorldService } from 'ZEPETO.World';
import { ItemContentsRequest, Mannequin, MannequinComponent, MannequinInteractable, MannequinPreviewer } from 'ZEPETO.Mannequin';
import { Object } from 'UnityEngine';
export default class MannequinScript extends ZepetoScriptBehaviour {
private _previewer: MannequinPreviewer;
Start() {
// 로그인한 ID를 기반으로 ZEPETO 캐릭터를 생성하는 코드
// ZepetoPlayers.instance.CreatePlayerWithUserId(WorldService.userId, SpawnInfo.Default, true);
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
const character = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// Mannequin Interactable Component 추가
character.gameObject.AddComponent<MannequinInteractable>();
});
// 모든 Mannequin 컴포넌트 찾기
const mannequins = Object.FindObjectsOfType<MannequinComponent>();
mannequins.forEach(m => {
// Collider에 들어가기
m.onActive.AddListener(contents => {
Mannequin.OpenUI(contents);
const zepetoContext = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character.Context;
this._previewer = new MannequinPreviewer(zepetoContext, contents);
this._previewer.PreviewContents();
});
// Collider에서 나가기
m.onCancel.AddListener(() => {
Mannequin.CloseUI();
this._previewer?.ResetContents();
});
});
}
}8) 객체에 스크립트를 추가한 후 [▶︎(재생)] 버튼을 눌러 실행하세요.

4단계 : 마네킹 구매 사용하기
마네킹 설정을 올바르게 완료하면, 마네킹 객체의 Collider 영역에 들어갈 때 상호작용 아이콘이 나타납니다.
아이콘을 클릭하면 설정한 아이템과 함께 구매 창이 나타납니다.

아이템을 클릭하면 착용해 볼 수 있습니다.
- 이미 소유하고 있는 아이템은 가격 대신 체크 표시로 표시됩니다. 맨니킨 객체의 콜라이더 영역을 벗어나면 착용이 취소되고 원래의 의상으로 돌아갑니다.

다음은 테스트 시나리오에 따른 구매 프로세스 작동 방식입니다.
STEP 5 : 맨니킨 멀티플레이어 동기화
멀티플레이어는 마네킹 기능을 사용하여 다른 플레이어가 착용한 의상을 동기화해야 합니다.
👍 기본 멀티플레이어 설정은 아래 내용을 작업하기 전에 완료되어야 합니다.
1) 클라이언트 스크립트를 추가합니다. ZEPETO > Typescript를 추가하고 스크립트 이름을 MannequinController로 작성합니다.
2) 아래와 같이 작성합니다.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { Room } from 'ZEPETO.Multiplay';
import { ClothesPreviewer, ItemContent, ItemContentsRequest, Mannequin, MannequinComponent, MannequinInteractable, MannequinPreviewer } from 'ZEPETO.Mannequin';
import { ZepetoContext } from 'Zepeto';
import { ZepetoPlayer, ZepetoPlayers } from 'ZEPETO.Character.Controller';
import { GameObject, Object, Canvas, WaitForSecondsRealtime, LayerMask } from 'UnityEngine';
import { Player } from 'ZEPETO.Multiplay.Schema';
import { ZepetoWorldMultiplay } from 'ZEPETO.World';
class CharacterItem {
property: string;
id: string;
}
class ChangedItem {
sessionId: string;
characterItems: CharacterItem[];
}
export default class MannequinController extends ZepetoScriptBehaviour {
private MESSAGE_TYPE = {
OnChangedItem: "OnChangedItem",
SyncChangedItem: "SyncChangedItem",
CheckChangedItem: "CheckChangedItem"
}
private multiplay: ZepetoWorldMultiplay;
private _room: Room;
private _previewer: MannequinPreviewer
private _context: ZepetoContext
private _userZepetoContexts: Map<string, ZepetoContext> = new Map<string, ZepetoContext>();
private _currentMannequinComponent: MannequinComponent = null;
private _selectMannequinComponent: MannequinComponent = null;
private _isOpenMannequinUI: boolean = false;
private _basicClothString = "basicCloth" as const;
Start() {
this.multiplay = Object.FindObjectOfType<ZepetoWorldMultiplay>();
Mannequin.OnOpenedShopUI.AddListener((item) => {
// 상점 버튼을 클릭했을 때
this.OpenedShopUI(item)
});
Mannequin.OnClosedShopUI.AddListener(() => {
// 닫기 버튼을 클릭했을 때
this.ClosedShopUI()
});
Mannequin.OnSelectedItem.AddListener((itemcontent: ItemContent, select: boolean) => {
// 아이템이 선택되었을 때의 동작
});
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
const myPlayer = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer;
// 마네킹
const character = myPlayer.character;
character.gameObject.AddComponent<MannequinInteractable>();
console.log("로컬 _context 설정됨");
this._context = character.Context;
const mannequins = Object.FindObjectsOfType<MannequinComponent>()
mannequins.forEach(mannequin => {
// 마네킹 충돌체에 들어갔을 때
mannequin.onActive.AddListener(contents => {
if (this._currentMannequinComponent != null && this._currentMannequinComponent == mannequin) {
return;
}
if (contents == null || contents.length == 0) {
console.log("마네킹 데이터 없음");
return;
}
if (this._isOpenMannequinUI) {
this.BreakMannequin();
}
this._selectMannequinComponent = mannequin;
Mannequin.OpenUI(contents);
console.log("onActive");
});
// [옵션] 마네킹 충돌체에서 나갔을 때
mannequin.onCancel.AddListener( () => {
if (this._currentMannequinComponent == null || this._currentMannequinComponent != mannequin) {
return;
}
this.BreakMannequin();
console.log("onCancel");
});
let iconCanvas = mannequin.gameObject.GetComponentInChildren<Canvas>(true);
if (iconCanvas != null) {
iconCanvas.gameObject.layer = LayerMask.NameToLayer("UI");
}
});
});
ZepetoPlayers.instance.OnAddedPlayer.AddListener((sessionId: string) => {
if (ZepetoPlayers.instance.GetPlayer(sessionId).isLocalPlayer) {
return;
}
const userContext = ZepetoPlayers.instance.GetPlayer(sessionId).character.Context;
this._userZepetoContexts.set(sessionId, userContext);
this._room.Send(this.MESSAGE_TYPE.CheckChangedItem, sessionId);
});
this.multiplay.RoomJoined += (room: Room) => {
this._room = room;
this.AddMessageHandler();
};
}
private AddMessageHandler() {
// [옵션] 각 플레이어의 옷을 동기화
this._room.AddMessageHandler<ChangedItem>(this.MESSAGE_TYPE.SyncChangedItem, message => {
console.log("syncChangedItem");
if (message == null) {
return;
}
if (false == this._userZepetoContexts.has(message.sessionId)) {
return;
}
let itemContents: ItemContent[] = [];
for (const characterItem of message.characterItems) {
let itemContent: ItemContent = new ItemContent();
itemContent.id = characterItem.id;
itemContent.property = parseInt(characterItem.property);
if (itemContent.id == this._basicClothString) {
itemContent.id = "";
}
itemContents.push(itemContent);
}
let clothesPreviewer:ClothesPreviewer = new ClothesPreviewer(this._userZepetoContexts.get(message.sessionId),itemContents);
clothesPreviewer.PreviewContents();
});
}
private ClosedShopUI() {
this._currentMannequinComponent = null;
this._isOpenMannequinUI = false;
}
private OpenedShopUI(items: ItemContent[]) {
this._isOpenMannequinUI = true;
this._currentMannequinComponent = this._selectMannequinComponent;
this._previewer = new MannequinPreviewer(this._context, items);
this._previewer.OnChanged.AddListener((changeValues) => {
let characterItems: CharacterItem[] = [];
for (const changeValue of changeValues) {
let characterItem: CharacterItem = new CharacterItem();
characterItem.id = changeValue.id;
characterItem.property = changeValue.property.toString();
if (characterItem.id == "") {
characterItem.id = this._basicClothString;
}
characterItems.push(characterItem);
}
this._room.Send(this.MESSAGE_TYPE.OnChangedItem, characterItems);
});
this._previewer.PreviewContents();
}
public BreakMannequin() {
Mannequin.CloseUI();
if (this._previewer) {
this._previewer.ResetContents();
this._previewer = null;
}
this._currentMannequinComponent = null;
this._isOpenMannequinUI = false;
}
}3) 계층 구조 만들기 > 빈 객체를 만들고 이름을 마네킹 컨트롤러로 지정합니다.
4) 방금 작성한 스크립트를 마네킹 컨트롤러에 추가하세요.

5) 다음으로, World.Multiplay > index.ts의 내용을 참조하여 서버 코드를 작성하세요.
import { Sandbox, SandboxOptions, SandboxPlayer } from 'ZEPETO.Multiplay';
import { Player, Transform, Vector3 } from 'ZEPETO.Multiplay.Schema';
class CharacterItem {
property: string;
id: string;
}
class ChangedItem {
sessionId: string;
characterItems: CharacterItem[];
}
enum Cloth {
TOP = "19",
BOTTOM = "20" ,
DRESS = "22"
}
export default class extends Sandbox {
private MESSAGE_TYPE = {
OnChangedItem: "OnChangedItem",
SyncChangedItem: "SyncChangedItem",
CheckChangedItem: "CheckChangedItem"
}
// Map<sessionId, Map<CharacterItem.property, CharacterItem.id>>
private ChangedItems: Map<string, Map<string, string>>;
onCreate(options: SandboxOptions) {
// 방 객체가 생성될 때 호출됩니다.
// 방 객체의 상태 또는 데이터 초기화를 처리합니다.
this.onMessage("onChangedTransform", (client, message) => {
const player = this.state.players.get(client.sessionId);
const transform = new Transform();
transform.position = new Vector3();
transform.position.x = message.position.x;
transform.position.y = message.position.y;
transform.position.z = message.position.z;
transform.rotation = new Vector3();
transform.rotation.x = message.rotation.x;
transform.rotation.y = message.rotation.y;
transform.rotation.z = message.rotation.z;
player.transform = transform;
});
this.onMessage("onChangedState", (client, message) => {
const player = this.state.players.get(client.sessionId);
player.state = message.state;
player.subState = message.subState; // 캐릭터 컨트롤러 V2
});
// 마네킹 서버 코드
this.ChangedItems = new Map<string, Map<string, string>>();
this.onMessage<CharacterItem[]>(this.MESSAGE_TYPE.OnChangedItem, (client, message) => {
// 옷을 덮어쓰고 새로운 부품을 설정합니다.
if (this.ChangedItems.has(client.userId)) {
const changedItemMap = this.ChangedItems.get(client.userId);
for (const characterItem of message) {
if (characterItem.property == Cloth.DRESS) {
// 드레스(22)의 경우, 상의(19)와 하의(20)를 제거합니다.
if (changedItemMap.has(Cloth.TOP)) {
changedItemMap.delete(Cloth.TOP);
}
if (changedItemMap.has(Cloth.BOTTOM)) {
changedItemMap.delete(Cloth.BOTTOM);
}
} else if (characterItem.property == Cloth.TOP || characterItem.property == Cloth.BOTTOM) {
// 상의(19) 또는 하의(20)인 경우 드레스를 제거합니다.
if (changedItemMap.has(Cloth.DRESS)) {
changedItemMap.delete(Cloth.DRESS);
}
}
changedItemMap.set(characterItem.property,characterItem.id);
console.log(`OnChangedItem old ${client.userId} : ${characterItem.property} // ${characterItem.id}`);
}
} else {
// 초기 등록
let changedItemMap: Map<string,string> = new Map<string, string>();
for (const characterItem of message) {
changedItemMap.set(characterItem.property,characterItem.id);
}
this.ChangedItems.set(client.sessionId,changedItemMap);
}
let changedItem: ChangedItem = new ChangedItem();
changedItem.sessionId = client.sessionId;
changedItem.characterItems = message;
console.log(`OnChangedItem : ${changedItem.sessionId}`);
for (const characterItem of changedItem.characterItems) {
console.log(` ::: ${characterItem.property} - ${characterItem.id} `);
}
this.broadcast(this.MESSAGE_TYPE.SyncChangedItem, changedItem, {except: client});
});
this.onMessage<string>(this.MESSAGE_TYPE.CheckChangedItem,(client, message) => {
if (false == this.ChangedItems.has(message)) {
return;
}
let changedItem: ChangedItem = new ChangedItem();
changedItem.sessionId = client.sessionId;
changedItem.characterItems = [];
for (const property of this.ChangedItems.get(message).keys()) {
let characterItem: CharacterItem = new CharacterItem();
characterItem.property = property;
characterItem.id = this.ChangedItems.get(message).get(property);
changedItem.characterItems.push(characterItem);
}
client.send<ChangedItem>(this.MESSAGE_TYPE.SyncChangedItem, changedItem );
});
}
onJoin(client: SandboxPlayer) {
// schemas.json에 정의된 플레이어 객체를 생성하고 초기 값을 설정합니다.
console.log(`[OnJoin] sessionId : ${client.sessionId}, HashCode : ${client.hashCode}, userId : ${client.userId}`)
const player = new Player();
player.sessionId = client.sessionId;
if (client.userId) {
player.zepetoUserId = client.userId;
}
// 클라이언트 객체의 고유 키 값인 sessionId를 사용하여 플레이어 객체를 관리합니다.
// 클라이언트는 players 객체에 add_OnAdd 이벤트를 추가하여 추가된 플레이어 객체에 대한 정보를 확인할 수 있습니다.
this.state.players.set(client.sessionId, player);
}
async onLeave(client: SandboxPlayer, consented?: boolean) {
// allowReconnection을 설정하면 회로에 대한 연결을 유지할 수 있지만 기본 가이드에서는 즉시 정리합니다.
// 클라이언트는 players 객체에 add_OnRemove 이벤트를 추가하여 삭제된 플레이어 객체에 대한 정보를 확인할 수 있습니다.
this.state.players.delete(client.sessionId);
if (this.ChangedItems.has(client.sessionId)) {
this.ChangedItems.delete(client.sessionId);
}
}
}6) 멀티플레이어 서버를 켜고 테스트하세요.
이벤트 기능
이벤트 기능은 ZEPETO Mannequin 1.1.0부터 사용할 수 있습니다.
ZEPETO.Mannequin.Mannequin
기능 | 설명 |
|---|---|
public static OnSelectedItem: UnityEngine_Events.UnityEvent$2<ItemContent, boolean>; | 마네킹 의상 구매 창에서 특정 항목이 선택될 때 호출되며, 선택된 항목 정보와 항목 선택이 boolean 값으로 전달됩니다. |
public static OnSucceededPurchaseItems: UnityEngine_Events.UnityEvent$1<ItemContent[]>; | 의상 구매가 완료되었을 때 호출되며, 구매한 항목 정보의 ItemContent 목록이 전달됩니다. |
public static OnFailedPurchaseItems: UnityEngine_Events.UnityEvent$1<ItemContent[]>; | 의상 구매가 실패했을 때 호출되며, 실패한 항목의 ItemContent 목록이 전달됩니다. |
public static OnAppliedItems: UnityEngine_Events.UnityEvent$1<ItemContent[]>; | 의상 구매가 성공적으로 완료된 후 구매한 항목을 착용하기로 선택했을 때 호출되며, 착용한 항목 정보의 ItemContent 목록이 전달됩니다. |
public static OnOpenedShopUI: UnityEngine_Events.UnityEvent$1<ItemContent[]>; | 마네킹 의상 구매 창이 열릴 때 호출되며, 구매 창의 항목 정보의 ItemContent 목록이 전달됩니다. |
public static OnClosedShopUI: UnityEngine_Events.UnityEvent; | 마네킹 의상 구매 창이 닫힐 때 호출됩니다. |
ZEPETO.Mannequin.BasePreviewer
기능 | 설명 |
|---|---|
public OnChanged: UnityEngine_Events.UnityEvent$1<ZEPETO_Mannequin_BasePreviewer.ChangedValue[]>; | 장비된 아이템 정보가 마네킹을 눌러 변경될 때 항상 호출되며, OnChagedValue 목록이 전달됩니다. |
OnChagedValue 클래스의 멤버 변수 정보는 다음과 같습니다:
public property : ZepetoPropertyFlag | 의류 부위 정보 |
|---|---|
public id : string | 아이템 ID |
Mannequin.WorldCamera
마네킹.월드카메라가 설정되지 않은 경우, 마네킹 상호작용 아이콘의 카메라는 낮은 깊이의 카메라로 설정됩니다.
특정 카메라를 설정하려면 마네킹.월드카메라를 사용하여 지정할 수 있습니다.
변수 | 설명 |
|---|---|
마네킹.월드카메라 | 마네킹 상호작용 아이콘의 카메라를 수동으로 설정할 수 있는 변수입니다. |
아래는 기존 MannequinScript에서 Mannequin.WorldCamera의 설정 예시입니다.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { ZepetoPlayers, SpawnInfo } from 'ZEPETO.Character.Controller';
import { WorldService } from 'ZEPETO.World';
import { ItemContentsRequest, Mannequin, MannequinComponent, MannequinInteractable, MannequinPreviewer } from 'ZEPETO.Mannequin';
import { Object } from 'UnityEngine';
export default class MannequinScript extends ZepetoScriptBehaviour {
private _previewer: MannequinPreviewer;
Start() {
// 로그인한 ID를 기반으로 ZEPETO 캐릭터를 생성하는 코드
// ZepetoPlayers.instance.CreatePlayerWithUserId(WorldService.userId, SpawnInfo.Default, true);
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
const character = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// Mannequin Interactable Component 추가
character.gameObject.AddComponent<MannequinInteractable>();
// Mannequin Icon World Canvas Camera를 ZEPETO Camera로 설정하는 코드
Mannequin.WorldCamera = ZepetoPlayers.instance.LocalPlayer.zepetoCamera.camera;
});
// 모든 Mannequin 컴포넌트 찾기
const mannequins = Object.FindObjectsOfType<MannequinComponent>();
mannequins.forEach(m => {
// Collider에 들어가기
m.onActive.AddListener(contents => {
Mannequin.OpenUI(contents);
const zepetoContext = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character.Context;
this._previewer = new MannequinPreviewer(zepetoContext, contents);
this._previewer.PreviewContents();
});
// Collider에서 나가기
m.onCancel.AddListener(() => {
Mannequin.CloseUI();
this._previewer?.ResetContents();
});
});
}
}
OnContentsLoaded API
Mannequin API를 사용하여 의류 아이템을 장착할 때 모든 의류 아이템이 완전히 로드되면 트리거되는 콜백이 추가되었습니다.
public OnContentsLoaded: UnityEngine_Events.UnityEvent$1<ZEPETO_Mannequin_BasePreviewer.ChangedValue[]>;
기존 MannequinScript에서 OnContentsLoaded를 설정하는 예는 다음과 같습니다.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { ZepetoPlayers, SpawnInfo } from 'ZEPETO.Character.Controller';
import { WorldService } from 'ZEPETO.World';
import { ItemContentsRequest, Mannequin, MannequinComponent, MannequinInteractable, MannequinPreviewer } from 'ZEPETO.Mannequin';
import { Object } from 'UnityEngine';
export default class MannequinScript extends ZepetoScriptBehaviour {
private _previewer: MannequinPreviewer;
Start() {
// 로그인한 ID를 기반으로 ZEPETO 캐릭터를 생성하는 코드
// ZepetoPlayers.instance.CreatePlayerWithUserId(WorldService.userId, SpawnInfo.Default, true);
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
const character = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// Mannequin Interactable Component 추가
character.gameObject.AddComponent<MannequinInteractable>();
});
// 모든 Mannequin 컴포넌트 찾기
const mannequins = Object.FindObjectsOfType<MannequinComponent>();
mannequins.forEach(m => {
// Collider에 들어가기
m.onActive.AddListener(contents => {
Mannequin.OpenUI(contents);
const zepetoContext = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character.Context;
this._previewer = new MannequinPreviewer(zepetoContext, contents);
// OnContentsLoaded 이벤트에 리스너 추가
this._previewer.OnContentsLoaded.AddListener((changedValues)=>{
console.log('Contents loaded:', changedValues);
});
this._previewer.PreviewContents();
});
// Collider에서 나가기
m.onCancel.AddListener(() => {
Mannequin.CloseUI();
this._previewer?.ResetContents();
});
});
}
}
