CREATE YOUR WORLD
Economy

ZEPETO Mannequin

28min
zepeto mannequin is a mannequin api package that supports the ability to try on/sell clothes you will be able to sell the clothing items you've made in the world you can create a mannequin wearing a designated costume of a zepeto character npc you can purchase clothing items by interacting with mannequins or objects https //www youtube com/watch?v=sag4h7b5om4 https //www youtube com/watch?v=sag4h7b5om4 step 1 install window → package manager → and install zepeto world package 1 21 15 or higher first after that, please install the zepeto module 1 0 8 package ❗️ caution as part of performance improvement, the standalone package has been integrated into zepeto module 1 0 8 and later version packages please delete any previously installed zepeto mannequin packages after removing existing packages, please install the zepeto module package version 1 0 8 or newer step 2 check item id to set on mannequin 👍 how to verify item id you can check the url that pops up when you click on the item product in zepeto studio copy the item id in the form of a random number, paste it into the unity editor, and paste 'cr ' in front of it 📘 if it's your first time making an item, please refer to the following guide \[ create items easily using the template editor (2d) docid\ cqp0hzxkf0ddpqfy6eey8 ] step 3 setting up the mannequin mannequin objects can be produced in a total of three ways only the items you've made and released can be set and sold in world with zepeto mannequin items that have been rejected in the review cannot be sold therefore, you must be logged in to unity in order to use the feature when you publish a package with mannequin function, you must also be logged in as an editor when using the zepeto template and zepeto model type mannequins, the resources consumed are equivalent to the number of zepeto characters entering, which may impact optimization if you need to place many zepeto character shaped mannequins within the world, it is recommended to select the simple type mannequin, and then utilize the zepeto basemodel https //studio zepeto me/console/download/652892d3a80a9f5505ed888f as an object step 3 1 simple type it's the most basic specific objects can be added as mannequin children to set the appearance 1\) adds an object to interact with 2\) collider must be added in order to interact with the object istrigger must be checked if not checked, it is automatically processed to recognize it as a trigger when you try to add a mannequin component without adding a collider, a warning window will appear as shown below 3\) add mannequin components to the object 4\) please set the following in the inspector icon the hanger icon is displayed by default you can change it to a custom icon icon position if not present, the icon appears in the object position with the mannequin component by default input the value after adding position object to make it appear on the desired location ids please fill out the item id of the clothing item you want to sell 5\) add an empty object and write the object name as mannequinscript 6\) add zepeto > typescript and write the script name as mannequinscript 7\) fill it out as below 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() { // code that creates a zepeto character based on the logged in id // zepetoplayers instance createplayerwithuserid(worldservice userid, spawninfo default, true); zepetoplayers instance onaddedlocalplayer addlistener(() => { const character = zepetoplayers instance localplayer zepetoplayer character; // add mannequin interactable component character gameobject addcomponent\<mannequininteractable>(); }); // find all mannequin components const mannequins = object findobjectsoftype\<mannequincomponent>(); mannequins foreach(m => { // enter the 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(); }); // exit the collider m oncancel addlistener(() => { mannequin closeui(); this previewer? resetcontents(); }); }); } } 8\) after adding the script to the object, press the \[▶︎(play)] button to run it step 3 2 zepeto model type you can set the appearance of a mannequin by adding an item id to the zepeto character npc 1\) create an empty object and name it as mannequin 2\) collider must be added in order to interact with the object istrigger must be checked if not checked, it is automatically processed to recognize it as a trigger 3\) add mannequin components to the object 4\) please set the following in the inspector icon the hanger icon is displayed by default you can change it to a custom icon icon position if not present, the icon appears in the object position with the mannequin component by default input the value after adding position object to make it appear on the desired location ids please fill out the item id of the clothing item you want to sell pose you can choose a pose and set it up in the future, we will provide the pose you want in the form of a pose id 👍 if you already have a mannequin script in your scene, you can skip the later steps 5\) add an empty object and write the object name as mannequinscript 6\) add zepeto > typescript and write the script name as mannequinscript 7\) fill it out as below 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() { // code that creates a zepeto character based on the logged in id // zepetoplayers instance createplayerwithuserid(worldservice userid, spawninfo default, true); zepetoplayers instance onaddedlocalplayer addlistener(() => { const character = zepetoplayers instance localplayer zepetoplayer character; // add mannequin interactable component character gameobject addcomponent\<mannequininteractable>(); }); // find all mannequin components const mannequins = object findobjectsoftype\<mannequincomponent>(); mannequins foreach(m => { // enter the 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(); }); // exit the collider m oncancel addlistener(() => { mannequin closeui(); this previewer? resetcontents(); }); }); } } 8\) after adding the script to the object, press the \[▶︎(play)] button to run it step 3 3 zepeto template type if you input a zepeto id, the clothes that the person is wearing will appear as mannequin however, if it is not the clothes you made, the clothes will not be shown 1\) create an empty object and name it as mannequin 2\) collider must be added in order to interact with the object istrigger must be checked if not checked, it is automatically processed to recognize it as a trigger 3\) add mannequin components to the object 4\) please set the following in the inspector icon the hanger icon is displayed by default you can change it to a custom icon icon position if not present, the icon appears in the object position with the mannequin component by default input the value after adding position object to make it appear on the desired location zepeto id please enter a zepeto id pose you can choose a pose and set it up in the future, we will provide the pose you want in the form of a pose id 👍 if you already have a mannequin script in your scene, you can skip the later steps 5\) add an empty object and write the object name as mannequinscript 6\) add zepeto > typescript and write the script name as mannequinscript 7\) fill it out as below 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() { // code that creates a zepeto character based on the logged in id // zepetoplayers instance createplayerwithuserid(worldservice userid, spawninfo default, true); zepetoplayers instance onaddedlocalplayer addlistener(() => { const character = zepetoplayers instance localplayer zepetoplayer character; // add mannequin interactable component character gameobject addcomponent\<mannequininteractable>(); }); // find all mannequin components const mannequins = object findobjectsoftype\<mannequincomponent>(); mannequins foreach(m => { // enter the 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(); }); // exit the collider m oncancel addlistener(() => { mannequin closeui(); this previewer? resetcontents(); }); }); } } 8\) after adding the script to the object, press the \[▶︎(play)] button to run it step 4 using mannequin purchases if you have completed the mannequin setting correctly, an icon will appear for interaction when you enter the collider area of the mannequin object when you click the icon, the purchase window will appear along with the item you set in the mannequin you can try it on by clicking on the item items that you already own will be marked with a check mark instead of a price when you leave the collider area of the mannequin object, the trying on will be canceled and you will return to your original outfit the following is how the purchase process works according to the test scenario step 5 mannequin multiplayer sync multiplayer requires synchronizing the costumes worn by other players using the mannequin function 👍 basic multiplayer setup should be completed before working on the contents below 1\) add a client script add zepeto > typescript and write the script name as mannequincontroller 2\) fill out as shown below 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) => { // when you click openshopbutton this openedshopui(item) }); mannequin onclosedshopui addlistener(() => { // when you click closeshopbutton this closedshopui() }); mannequin onselecteditem addlistener((itemcontent itemcontent, select boolean) => { // action when item is selected }); zepetoplayers instance onaddedlocalplayer addlistener(() => { const myplayer = zepetoplayers instance localplayer zepetoplayer; // mannequin const character = myplayer character; character gameobject addcomponent\<mannequininteractable>(); console log("local context set"); this context = character context; const mannequins = object findobjectsoftype\<mannequincomponent>() mannequins foreach(mannequin => { // when you enter mannequin collider mannequin onactive addlistener(contents => { if (this currentmannequincomponent != null && this currentmannequincomponent == mannequin) { return; } if (contents == null || contents length == 0) { console log("no mannequin data"); return; } if (this isopenmannequinui) { this breakmannequin(); } this selectmannequincomponent = mannequin; mannequin openui(contents); console log("onactive"); }); // \[option] when you leave mannequin collider 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() { // \[option] synchronize each player's clothes 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\) create hierarchy > empty object and name it mannequin controller 4\) add the script you just wrote to the mannequin controller 5\) next, write the server code by referring to the contents below in 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) { // called when the room object is created // handle the state or data initialization of the room object 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; // character controller v2 }); // mannequin server code this changeditems = new map\<string, map\<string, string>>(); this onmessage\<characteritem\[]>(this message type onchangeditem, (client, message) => { // overwrite clothes and set new parts if (this changeditems has(client userid)) { const changeditemmap = this changeditems get(client userid); for (const characteritem of message) { if (characteritem property == cloth dress) { // in the case of a dress (22), remove the top (19) and bottom (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) { // remove the dress if it is a top (19) or bottom (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 { // initial registration 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) { // create the player object defined in schemas json and set the initial value 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; } // manage the player object using sessionid, a unique key value of the client object // the client can check the information about the player object added by set by adding the add onadd event to the players object this state players set(client sessionid, player); } async onleave(client sandboxplayer, consented? boolean) { // by setting allowreconnection, it is possible to maintain connection for the circuit, but clean up immediately in the basic guide // the client can check the information about the deleted player object by adding the add onremove event to the players object this state players delete(client sessionid); if (this changeditems has(client sessionid)) { this changeditems delete(client sessionid); } } } 6\) turn on the multiplayer server and test it event function the event function is available from zepeto mannequin 1 1 0 zepeto mannequin mannequin function description public static onselecteditem unityengine events unityevent$2\<itemcontent, boolean>; called when a specific item is selected in the mannequin costume purchase window, and the itemcontent of selected item information and item selection are transferred to the boolean value public static onsucceededpurchaseitems unityengine events unityevent$1\<itemcontent\[]>; called when the clothing purchase is completed, and the itemcontent list of purchased item information is brought over public static onfailedpurchaseitems unityengine events unityevent$1\<itemcontent\[]>; called when the purchase of a clothing has failed, and the itemcontent list of failed item's information is brought over public static onapplieditems unityengine events unityevent$1\<itemcontent\[]>; called when you choose to wear the item you purchased after the successful purchase of the clothing, and the itemcontent list of the item information you have worn will be brought over public static onopenedshopui unityengine events unityevent$1\<itemcontent\[]>; called when the mannequin costume purchase window is opened, and the itemcontent list of item information in the purchase window is brought over public static onclosedshopui unityengine events unityevent; called when the mannequin costume purchase window is closed zepeto mannequin basepreviewer function description public onchanged unityengine events unityevent$1\<zepeto mannequin basepreviewer changedvalue\[]>; it is always called when the equipped item information is changed by pressing the mannequin, and the onchagedvalue list is brought over the member variable information for the onchagedvalue class is as follows public property zepetopropertyflag clothing part information public id string item id mannequin worldcamera if mannequin worldcamera is not set, the camera for the mannequin interaction icon will be set as a camera with low depth if you wish to set a specific camera, you can use mannequin worldcamera to designate one variable description mannequin worldcamera a variable that allows you to manually set the camera for the mannequin interaction icon below is an example setting of mannequin worldcamera on an existing mannequinscript 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() { // code that creates a zepeto character based on the logged in id // zepetoplayers instance createplayerwithuserid(worldservice userid, spawninfo default, true); zepetoplayers instance onaddedlocalplayer addlistener(() => { const character = zepetoplayers instance localplayer zepetoplayer character; // add mannequin interactable component character gameobject addcomponent\<mannequininteractable>(); // code to set up the mannequin icon world canvas camera as the zepeto camera mannequin worldcamera = zepetoplayers instance localplayer zepetocamera camera; }); // find all mannequin components const mannequins = object findobjectsoftype\<mannequincomponent>(); mannequins foreach(m => { // enter the 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(); }); // exit the collider m oncancel addlistener(() => { mannequin closeui(); this previewer? resetcontents(); }); }); } } oncontentsloaded api a callback has been added that is triggered when all clothing items are fully loaded while using the mannequin api to equip clothing items api public oncontentsloaded unityengine events unityevent$1\<zepeto mannequin basepreviewer changedvalue\[]>; an example of setting oncontentsloaded in the existing mannequinscript is as follows mannequinscript 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() { // code that creates a zepeto character based on the logged in id // zepetoplayers instance createplayerwithuserid(worldservice userid, spawninfo default, true); zepetoplayers instance onaddedlocalplayer addlistener(() => { const character = zepetoplayers instance localplayer zepetoplayer character; // add mannequin interactable component character gameobject addcomponent\<mannequininteractable>(); }); // find all mannequin components const mannequins = object findobjectsoftype\<mannequincomponent>(); mannequins foreach(m => { // enter the collider m onactive addlistener(contents => { mannequin openui(contents); const zepetocontext = zepetoplayers instance localplayer zepetoplayer character context; this previewer = new mannequinpreviewer(zepetocontext, contents); // adding listener to oncontentsloaded event this previewer oncontentsloaded addlistener((changedvalues)=>{ console log('contents loaded ', changedvalues); }); this previewer previewcontents(); }); // exit the collider m oncancel addlistener(() => { mannequin closeui(); this previewer? resetcontents(); }); }); } }