Studio GuideWorld SDK Guide
Log In

Changing ZEPETO character color and worn item color

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.

Zepeto Context > body > body Material

Zepeto Context > body > body Material


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.

Zepeto Context > body > Item > Item Material

Zepeto Context > body > Item > Item Material


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!