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 可交互组件
character.gameObject.AddComponent<MannequinInteractable>();
});
// 查找所有 Mannequin 组件
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-2 : ZEPETO 模型类型

您可以通过将物品 ID 添加到 ZEPETO 角色 NPC 来设置人形的外观。
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) 必须添加碰撞体以与对象进行交互。
- 必须勾选 isTrigger。如果未勾选,则会自动处理为识别为触发器。
3) 将人形组件添加到对象中。
4) 请在检查器中设置以下内容。
- 图标:默认显示衣架图标。您可以将其更改为自定义图标。
- 图标位置:如果不存在,图标默认出现在带有人形组件的对象位置。
- 输入值后添加位置对象,以使其出现在所需位置。
- zepeto id:请输入 ZEPETO 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;
// 添加 Mannequin 可交互组件
character.gameObject.AddComponent<MannequinInteractable>();
});
// 查找所有 Mannequin 组件
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) 将脚本添加到对象后,按 [▶︎(播放)] 按钮运行它。

步骤 4 : 使用 Mannequin 购买
如果您正确完成了人形设置,当您进入人形对象的碰撞体区域时,将出现一个交互图标。
当您点击图标时,购买窗口将出现,并显示您在模特上设置的物品。

您可以通过点击物品来试穿。
- 您已经拥有的物品将用勾号标记,而不是价格。 当您离开模特物体的碰撞区域时,试穿将被取消,您将返回到原来的服装。

以下是根据测试场景购买过程的工作方式。
步骤 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 管理玩家对象,这是客户端对象的唯一键值。
// 客户端可以通过将 add_OnAdd 事件添加到 players 对象来检查有关玩家对象的信息。
this.state.players.set(client.sessionId, player);
}
async onLeave(client: SandboxPlayer, consented?: boolean) {
// 通过设置 allowReconnection,可以保持电路的连接,但在基本指南中立即清理。
// 客户端可以通过将 add_OnRemove 事件添加到 players 对象来检查有关已删除玩家对象的信息。
this.state.players.delete(client.sessionId);
if (this.ChangedItems.has(client.sessionId)) {
this.ChangedItems.delete(client.sessionId);
}
}
}6) 打开多人服务器并进行测试。
事件功能
事件功能可从 ZEPETO Mannequin 1.1.0 开始使用。
ZEPETO.模特.模特
功能 | 描述 |
|---|---|
public static OnSelectedItem: UnityEngine_Events.UnityEvent$2<ItemContent, 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.模特.基础预览器
功能 | 描述 |
|---|---|
public OnChanged: UnityEngine_Events.UnityEvent$1<ZEPETO_Mannequin_BasePreviewer.ChangedValue[]>; | 每当通过按压模型更改装备物品信息时,都会调用此方法,并传递 OnChagedValue 列表。 |
OnChagedValue 类的成员变量信息如下:
public property : ZepetoPropertyFlag | 服装部件信息 |
|---|---|
public id : string | 物品 ID |
人偶.世界相机
如果未设置人偶.世界相机,则人偶交互图标的相机将设置为低深度的相机。
如果您希望设置特定的相机,可以使用人偶.世界相机来指定一个。
变量 | 描述 |
|---|---|
人偶.世界相机 | 一个允许您手动设置人偶交互图标相机的变量。 |
以下是现有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可交互组件
character.gameObject.AddComponent<MannequinInteractable>();
// 代码将Mannequin图标世界画布相机设置为ZEPETO相机
Mannequin.WorldCamera = ZepetoPlayers.instance.LocalPlayer.zepetoCamera.camera;
});
// 查找所有Mannequin组件
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();
});
});
}
}
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 组件
character.gameObject.AddComponent<MannequinInteractable>();
});
// 查找所有 Mannequin 组件
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);
// 添加 OnContentsLoaded 事件的监听器
this._previewer.OnContentsLoaded.AddListener((changedValues)=>{
console.log('内容已加载:', changedValues);
});
this._previewer.PreviewContents();
});
// 退出碰撞体
m.onCancel.AddListener(() => {
Mannequin.CloseUI();
this._previewer?.ResetContents();
});
});
}
}
