This guide aims to assist in creating engaging content.
Changing the Color of ZEPETO Characters
ZEPETO characters are instantiated at runtime as a ZepetoCharacter object.
If you inspect the structure of ZepetoCharacter, you'll find a sub-object named Zepeto Context. Further within Zepeto Context, there's another object named body.
By replacing the body(Clone) Material of the body Object at runtime using scripts, you can change the color of the ZEPETO character.
For non-animated avatars, this approach changes the color of the entire face and body.
However, for animated avatars, you need to also modify the body(Clone) Material of the ANIME_BASEMODEL, which is a child of the body Object.
Please note that Material replacements are feasible with Material arrays of the same length.
Unity Materials
https://docs.unity3d.com/2020.3/Documentation/Manual/Materials.html
Below is a sample code that changes the body color of the Local Player.
Make sure to implement the logic so the character's color is changed only after the character has loaded.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script'
import {LocalPlayer, SpawnInfo, ZepetoCharacter, ZepetoCharacterCreator, ZepetoPlayers} from "ZEPETO.Character.Controller";
import {ZepetoPropertyFlag} from "Zepeto";
import { GameObject, Material, Renderer, SkinnedMeshRenderer, Transform, WaitForSeconds } from 'UnityEngine';
import { Button } from 'UnityEngine.UI';
export default class ChangeSkinColor extends ZepetoScriptBehaviour {
public newColorMaterial : Material;
public changeColorButton : Button;
public originalColorButton : Button;
private _originalColorMaterial : Material;
private _originalAnimeMaterials : Material[];
private _animeRend : Renderer;
private _bodyRend : Renderer;
private _bodyRends : Renderer[];
private _localCharacter: ZepetoCharacter;
Start() {
// Find the local player and Set it to _localCharacter
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
this._localCharacter = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// Find the material of the local player's zepeto context
this._bodyRend= this._localCharacter.Context.GetComponentInChildren<SkinnedMeshRenderer>();
// Store the original material
this._originalColorMaterial = this._bodyRend.material;
// Determine if it is an animated avatar and save related information
this._bodyRends= this._localCharacter.GetComponentsInChildren<SkinnedMeshRenderer>();
this._bodyRends.forEach((currentRenderer) =>{
if(currentRenderer.name.includes("ANIME_BASEMODEL")){
this._animeRend = currentRenderer;
this._originalAnimeMaterials = this._animeRend.sharedMaterials;
}
});
});
// Replace with the preset material when the button is pressed
this.changeColorButton.onClick.AddListener(() => {
if(this._localCharacter != null) {
this._bodyRend.material = this.newColorMaterial;
if(this._animeRend != null) {
let tempMaterials : Material[] = [this._animeRend.sharedMaterials[0],this._animeRend.sharedMaterials[1],this.newColorMaterial,this._animeRend.sharedMaterials[3]];
this._animeRend.sharedMaterials = tempMaterials;
}
}
});
// Return to the original material when the button is pressed
this.originalColorButton.onClick.AddListener(() => {
if(this._localCharacter != null) {
this._bodyRend.material = this._originalColorMaterial;
if(this._animeRend != null) {
this._animeRend.sharedMaterials = this._originalAnimeMaterials;
}
}
});
}
}
Caution
- Altering the body Material may result in the ZEPETO avatar's makeup not being displayed correctly.
Changing the Color of Worn Items
Worn items are instantiated as sub-objects under the body Object.
You can check the applied Material for each item from the Materials section of the item object.
By replacing the Materials at runtime using scripts, you can change the color of the items.
Below is a sample code that changes the color of the first item worn by the Local Player.
Ensure that the item's color is changed only after the character has loaded.
import { ZepetoScriptBehaviour } from 'ZEPETO.Script'
import {LocalPlayer, ZepetoCharacter, ZepetoPlayers} from "ZEPETO.Character.Controller";
import { GameObject, Material, Renderer, SkinnedMeshRenderer, Transform, WaitForSeconds } from 'UnityEngine';
import { Button } from 'UnityEngine.UI';
export default class ChangeSkinColor extends ZepetoScriptBehaviour {
public newColorMaterial : Material;
public changeColorButton : Button;
public originalColorButton : Button;
private _originalColorMaterial : Material;
private _body : GameObject;
private _itemRend : Renderer;
private _localCharacter: ZepetoCharacter;
Start() {
// Find the local player and Set it to _localCharacter
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
this._localCharacter = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// Access the body of the local player's zepeto context
this._body = this._localCharacter.Context.GetComponentInChildren<SkinnedMeshRenderer>().gameObject;
// Access the material of the first child item of the body
this._itemRend = this._body.transform.GetChild(0).GetComponent<SkinnedMeshRenderer>();
// Store the original material
this._originalColorMaterial = this._itemRend.material;
});
// Replace with the preset material when the button is pressed
this.changeColorButton.onClick.AddListener(() => {
if(this._localCharacter != null) {
this._itemRend.material = this.newColorMaterial;
}
});
// Return to the original material when the button is pressed
this.originalColorButton.onClick.AddListener(() => {
if(this._localCharacter != null) {
this._itemRend.material = this._originalColorMaterial;
}
});
}
}
- Code Explanation
this.body.transform.GetChild(0)
refers to the first item among the worn items, i.e., the item at index 0.- You can adapt this to change the color of other worn items.
- For items using multiple Materials, remember that Material replacements require Material arrays of the same length.
Changing the Color of Both ZEPETO Characters and All Items
By leveraging the insights we've gained so far, you can modify the color of both the character and all items uniformly.
Here's a sample code that alters the color of the Local Player's character and item colors entirely when the "Change Color" button is clicked and reverts back to the original when the "Original Color" button is clicked:
import { ZepetoScriptBehaviour } from 'ZEPETO.Script'
import {LocalPlayer, ZepetoCharacter, ZepetoPlayers} from "ZEPETO.Character.Controller";
import { GameObject, Material, Renderer, SkinnedMeshRenderer, Transform, WaitForSeconds } from 'UnityEngine';
import { Button } from 'UnityEngine.UI';
export default class ChangeAllMaterial extends ZepetoScriptBehaviour {
public newColorMaterial : Material;
public changeColorButton : Button;
public originalColorButton : Button;
private _originalMaterials : Material[] = new Array();
private _bodyRends : Renderer[];
private _localCharacter: ZepetoCharacter;
Start() {
// Find the local player and Set it to _localCharacter
ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
this._localCharacter = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
// Save to keep original materials
this._bodyRends= this._localCharacter.GetComponentsInChildren<SkinnedMeshRenderer>();
this._bodyRends.forEach((currentRenderer) =>{
for(let i=0; i<currentRenderer.sharedMaterials.length;i++){
this._originalMaterials.push(currentRenderer.sharedMaterials[i]);
}
});
});
// Replace with the preset material when the button is pressed
this.changeColorButton.onClick.AddListener(() => {
if(this._localCharacter != null) {
this._bodyRends.forEach((currentRenderer) =>{
let tempMaterials : Material[] = new Array();
for(let i=0; i<currentRenderer.sharedMaterials.length;i++){
tempMaterials.push(this.newColorMaterial);
}
currentRenderer.sharedMaterials = tempMaterials;
});
}
});
// Return to the original material when the button is pressed
this.originalColorButton.onClick.AddListener(() => {
if(this._localCharacter != null) {
let indexNum = 0;
this._bodyRends= this._localCharacter.GetComponentsInChildren<SkinnedMeshRenderer>();
this._bodyRends.forEach((currentRenderer) =>{
let tempMaterials : Material[] = new Array();
for(let i=0; i<currentRenderer.sharedMaterials.length;i++){
tempMaterials.push(this._originalMaterials[indexNum]);
indexNum++;
}
currentRenderer.sharedMaterials = tempMaterials;
});
}
});
}
}
Tip
- This method is not only applicable to the Local Player but also to any ZEPETO characters created at runtime, including NPC characters.
- Feel free to get creative and apply it in fun ways!