---
title: Membuat sebuah NPC
slug: world-sdk-guide-id/membuat-sebuah-npc
docTags: 
createdAt: 2024-09-02T08:34:13.135Z
---

Pelajari cara membuat NPC dari Karakter ZEPETO.

Terapkan skrip contoh yang disediakan untuk setiap fitur untuk menambahkan NPC pilihan Anda ke Dunia Anda.



Buat NPC menggunakan ID ZEPETO.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-6t3GXLriXPmQFtlwSRTpI-20240904-102416.png" size="64" width="2072" height="1702" position="center" showCaption="false"}



:::hint{type="danger"}
- Penampilan NPC dan barang yang dikenakan akan sama dengan ID ZEPETO yang dimasukkan.
- Disarankan untuk menyiapkan karakter ZEPETO dengan penampilan tertentu sebelum membuat NPC.
:::



### Mengatur objek lokasi di mana NPC akan dibuat



- Terapkan kode pembuatan karakter ZEPETO di Scene Anda secara default.

:::hint{type="info"}
**📘&#x20;**&#x53;ilakan merujuk ke panduan berikut. \[[Buat Karakter ZEPETO](docId:6xBDpw8HvdwOp3dXH17Ww)]
:::



- Buat Hierarki > Buat Objek Kosong dan ganti namanya menjadi NPC.
  - Sebuah objek untuk menyimpan lokasi di mana NPC akan dibuat.
  - Atur Posisi, Rotasi.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-Q1f-ytfigV8Dq1mSrbw9H-20240904-102416.png)



### Menulis skrip pembuatan NPC



1\) Buat Proyek > Buat > ZEPETO > TypeScript dan ganti namanya menjadi NPCCreator.

2\) Tulis skrip contoh seperti di bawah ini.

```typescript
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { SpawnInfo, ZepetoCharacter, ZepetoCharacterCreator } from 'ZEPETO.Character.Controller';
  
export default class NPCCreator extends ZepetoScriptBehaviour {
  
    // ZEPETO ID dari NPC
    public zepetoId: string;
    // Objek karakter NPC
    private _npc: ZepetoCharacter;
  
    Start() {
        // Buat instance baru dari SpawnInfo dan atur posisinya serta rotasinya berdasarkan transformasi objek
        const spawnInfo = new SpawnInfo();
        spawnInfo.position = this.transform.position;
        spawnInfo.rotation = this.transform.rotation;
  
        // Gunakan ZepetoCharacterCreator untuk membuat karakter baru berdasarkan Zepeto ID dan menetapkannya ke variabel _npc
        ZepetoCharacterCreator.CreateByZepetoId(this.zepetoId, spawnInfo, (character: ZepetoCharacter) => {
            this._npc = character;
        })
    }
  
}
```



Alur skrip adalah sebagai berikut:

- Start()
  - Buat NPC di lokasi objek NPC menggunakan fungsi ZepetoCharacterCreator.CreateByZepetoId() dan simpan di \_npc.



3\) Setelah Anda selesai menulis skrip, tambahkan skrip ke objek NPC.

4\) Tetapkan Zepeto Id di inspector.

- Zepeto Id : ID ZEPETO dari NPC.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-eddQgXlREGkYHgxSGffvE-20240904-102416.png "Contoh Layar Pengaturan Skrip")



5\) Tekan tombol play untuk mengeksekusi dan NPC akan dibuat.

6\) Tambahkan objek lokasi NPC dengan cara yang sama, dan tambahkan skrip NPC untuk membuat beberapa NPC dengan mudah.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-n-EI7bbyvulqtYh2xM4Fi-20240904-102416.png" size="70" width="2162" height="1554" position="center" showCaption="false"}



# Pelabelan NPC



Anda dapat memberi label pada NPC Anda dengan label nama untuk membedakannya dari pemain.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-1wBC20gR8-tyjJfLNDdAz-20240904-102416.png" size="64" width="2240" height="1766" position="center" showCaption="false"}



### Untuk membuat Prefab Kanvas Name Tag



1\) Buat Hierarki > UI > Kanvas dan ganti namanya menjadi PrefNameTagCanvas.

- Atur Mode Render ke World Space.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-V4rHI2xgMMHikJ1q6_HxT-20240904-102416.png" size="50" width="422" height="698" position="center" caption="Contoh Pengaturan Kanvas" showCaption="true"}



2\) Buat Hierarki > UI > Teks sebagai anak dari PrefNameTagCanvas dan ganti namanya menjadi NameTagText.

- Teks untuk mewakili nama.
- Tambahkan komponen Content Size Fitter untuk membuat teks dengan ukuran yang tepat.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-K-9H7mFnVL2HIgV3MAI8k-20240904-102416.png "Contoh Pengaturan Teks")



3\) Setelah selesai, seret ke jendela Proyek untuk menjadikannya Prefab, dan kemudian hapus PrefNameTagCanvas yang masih ada di penyorot.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-3P9qMV8rV0RdM4ejqtS2A-20240904-102416.png "Contoh Konfigurasi Prefab")



### Membuat Skrip Nama Tag NPC



1\) Buat Proyek > Buat > ZEPETO > TypeScript dan ganti namanya menjadi NPCCreatorWithNameTag.

2\) Tulis skrip contoh seperti yang ditunjukkan di bawah ini.

```typescript
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { KnowSockets, SpawnInfo, ZepetoCharacter, ZepetoCharacterCreator } from 'ZEPETO.Character.Controller';
import { Canvas, Camera, Vector3, Object, GameObject } from 'UnityEngine';
import { Text } from 'UnityEngine.UI';

export default class NPCCreatorWithNameTag extends ZepetoScriptBehaviour {

    // ZEPETO ID dari NPC
    public zepetoId: string;
    // Nama yang akan ditampilkan di label nama 
    public nameTag: string;
    // Prefab dari objek game kanvas label nama
    public nameTagPrefab: GameObject;
    // Nilai offset sumbu Y dari objek game kanvas label nama
    public nameTagYOffset: number;

    // Objek karakter NPC
    private _npc: ZepetoCharacter;
    // Objek game kanvas label nama NPC
    private _npcNameTagObject: GameObject;
    // Teks di dalam objek game kanvas label nama
    private _npcNameTagText: Text;
    // Kanvas label nama
    private _canvas: Canvas;
    // Kamera Dunia
    private _cachedWorldCamera: Camera;

    Start() {
        // Buat instance baru dari SpawnInfo dan atur posisinya serta rotasinya berdasarkan transform objek
        const spawnInfo = new SpawnInfo();
        spawnInfo.position = this.transform.position;
        spawnInfo.rotation = this.transform.rotation;

        // Gunakan ZepetoCharacterCreator untuk membuat karakter baru berdasarkan ZEPETO ID dan menetapkannya ke variabel _npc
        ZepetoCharacterCreator.CreateByZepetoId(this.zepetoId, spawnInfo, (character: ZepetoCharacter) => {
            this._npc = character;

            // Atur label nama
            this.SetNameTag();
        })
    }

    // Atur label nama
    SetNameTag() {
        // Buat objek game kanvas label nama secara dinamis
        this._npcNameTagObject = Object.Instantiate(this.nameTagPrefab) as GameObject;
        
        // Atur parent dari transform objek game kanvas label nama menjadi transform NPC.
        this._npcNameTagObject.transform.SetParent(this._npc.transform);
        
        // Atur posisi objek game kanvas label nama di atas kepala NPC
        this._npcNameTagObject.transform.position = Vector3.op_Addition(this._npc.GetSocket(KnowSockets.HEAD_UPPER).position, new Vector3(0, this.nameTagYOffset,0));

        // Atur teks di dalam label nama
        this._npcNameTagText = this._npcNameTagObject.GetComponentInChildren<Text>();
        this._npcNameTagText.text = this.nameTag;

        this._canvas = this._npcNameTagObject.GetComponent<Canvas>();
        this._cachedWorldCamera = Object.FindObjectOfType<Camera>();
        this._canvas.worldCamera = this._cachedWorldCamera;
    }

    private Update() {
        if (this._canvas != null) {
            this.UpdateCanvasRotation();
        }
    }

    // Perbarui rotasi kanvas label nama agar menghadap kamera
    private UpdateCanvasRotation() {
        this._canvas.transform.LookAt(this._cachedWorldCamera.transform);
        this._canvas.transform.Rotate(0, 180, 0);
    }

}
```



Alur skrip adalah sebagai berikut:

- Mulai()
  - Panggil fungsi kustom SetNameTag().
- SetNameTag()
  - Secara dinamis menghasilkan label nama untuk NPC dan menyesuaikan posisi label nama yang dihasilkan di atas kepala NPC
  - Atur teks di dalam label nama.
- Perbarui()
  - Panggil fungsi kustom UpdateCanvasRotation() untuk memutar kanvas agar sesuai dengan kamera.



3\) Setelah Anda selesai menulis skrip, tambahkan ke objek NPC.

4\) Di Inspector, tetapkan Zepeto Id, Label Nama, Prefab Label Nama, dan Offset Y Label Nama.

- Label Nama: Nama yang akan muncul di label nama NPC.
- Prefab Label Nama: Prefab kanvas label nama.
- Offset Y Label Nama: Variabel yang menyimpan nilai offset sumbu-y untuk objek Kanvas Label Nama. Ketika Anda menempatkan label nama di atas kepala karakter, Anda dapat menyesuaikan jarak antara karakter dan label nama.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-1gmj-fFGOz1PvkIsEgzr1-20240904-102416.png" size="86" width="498" height="342" position="center" caption="Contoh Layar Pengaturan Skrip" showCaption="true"}



5\) tekan tombol putar untuk mengeksekusi, dan NPC dengan nama tag akan dibuat.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-oTdyZ4V5rP2aOM-FG7gDz-20240904-102416.png" size="60" width="2058" height="1572" position="center" showCaption="false"}



# Mengendalikan Perilaku NPC



Anda dapat mengendalikan tindakan NPC.



## Melompat



::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-kQCSmRiBt_OP-OkBovT_P-20240904-102417.gif" size="68" width="800" height="639" position="center" showCaption="false"}



Gunakan ZEPETO Character API untuk membuat NPC melompat.

Anda dapat menggunakan ZEPETO Character API untuk menerapkan berbagai perilaku.

:::hint{type="info"}
**📘&#x20;**&#x53;ilakan merujuk ke panduan berikut. \[[Karakter ZEPETO](docId\:XZ6ZLJtc-HieRlBBDaort)]
:::



### Membuat skrip NPC Jump

1\) Pergi ke Proyek > Buat > ZEPETO > Buat TypeScript dan ganti namanya menjadi NPCJump.

2\) Tulis skrip contoh seperti yang ditunjukkan di bawah ini.

```typescript
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { SpawnInfo, ZepetoCharacter, ZepetoCharacterCreator } from 'ZEPETO.Character.Controller';
import { WaitForSeconds } from 'UnityEngine';

export default class NPCJump extends ZepetoScriptBehaviour {

    // ID ZEPETO dari NPC
    public zepetoId: string;
    // Objek karakter NPC
    private _npc: ZepetoCharacter;

    Start() {
        // Buat instance baru dari SpawnInfo dan atur posisinya serta rotasinya berdasarkan transformasi objek
        const spawnInfo = new SpawnInfo();
        spawnInfo.position = this.transform.position;
        spawnInfo.rotation = this.transform.rotation;

        // Gunakan ZepetoCharacterCreator untuk membuat karakter baru berdasarkan ID ZEPETO dan menetapkannya ke variabel _npc
        ZepetoCharacterCreator.CreateByZepetoId(this.zepetoId, spawnInfo, (character: ZepetoCharacter) => {
            this._npc = character;
            
            this.StartCoroutine(this.JumpCoroutine());
        });
    }

    *JumpCoroutine() {
        // Loop tak terbatas untuk terus menerus
        while (true) {
            // Panggil metode Jump() dari ZepetoCharacter untuk membuatnya melompat
            this._npc.Jump();

            // Tunggu selama 5 detik 
            yield new WaitForSeconds(5);
        }
    }
}
```

Alur skrip adalah sebagai berikut:

- Mulai()
  - Panggil coroutine JumpCoroutine().
- JumpCoroutine()
  - Panggil metode Jump() untuk membuat karakter NPC melompat setiap 5 detik.



3\) Setelah Anda selesai menulis skrip, tambahkan skrip ke objek NPC.

4\) Tekan tombol Putar dan NPC akan melompat.



## Gerakan



::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-IxShgv_lsEN9qbJbGhkqH-20240904-102419.gif" size="68" width="800" height="639" position="center" showCaption="false"}



Gunakan Animator Controller untuk menerapkan gerakan untuk NPC.

Anda dapat menggunakan Animator Controller untuk menerapkan berbagai perilaku yang lebih luas.

:::hint{type="info"}
**📘 Unity Animator Controller**
[https://docs.unity3d.com/Manual/class-AnimatorController.html](https://docs.unity3d.com/Manual/class-AnimatorController.html)
:::



### Mempersiapkan klip animasi Anda



- Gunakan panduan berikut untuk mempersiapkan klip animasi gerakan untuk NPC Anda lakukan.

:::hint{type="info"}
**📘&#x20;**&#x53;ilakan merujuk ke panduan berikut.

- \[[Menggunakan animasi karakter ZEPETO](docId\:STbveD_w7FItuvnR-hCLE)]
- \[[Cara menerapkan animasi kustom](docId\:ZfFQrboHetydztIovUlKu)]
:::



### Membuat Animator



1\) Proyek > Buat > Buat Pengontrol Animator dan ganti namanya menjadi NPCAnimatorController.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-yRqBb0vmcd1uU09TWYxTZ-20240904-102416.png" size="68" width="612" height="773" position="center" showCaption="false"}



2\) Di tab Animator, Buat Status > Kosong.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-DimxMvgUSMikvwjWAXS49-20240904-102416.png)



3\) Di Inspector, ganti namanya dengan tepat dan tetapkan klip animasi ke Motion.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-M6b-vT5cSD0ZssJRPRq1w-20240904-102416.png)



### Membuat Skrip Gesture NPC



1\) Buat Proyek > Buat > ZEPETO > TypeScript dan ganti namanya menjadi NPCGesture.

2\) Tulis skrip contoh seperti yang ditunjukkan di bawah ini.

```typescript
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { SpawnInfo, ZepetoCharacter, ZepetoCharacterCreator } from 'ZEPETO.Character.Controller';
import { Animator, RuntimeAnimatorController } from 'UnityEngine';

export default class NPCGesture extends ZepetoScriptBehaviour {

    // ID ZEPETO dari NPC
    public zepetoId: string;
    // Animator Controller dari NPC
    public npcAnimator: RuntimeAnimatorController;

    // Objek karakter NPC
    private _npc: ZepetoCharacter;

    Start() {

        // Buat instance baru dari SpawnInfo dan atur posisinya serta rotasinya berdasarkan transformasi objek
        const spawnInfo = new SpawnInfo();
        spawnInfo.position = this.transform.position;
        spawnInfo.rotation = this.transform.rotation;

        // Gunakan ZepetoCharacterCreator untuk membuat karakter baru berdasarkan ID ZEPETO dan menetapkannya ke variabel _npc
        ZepetoCharacterCreator.CreateByZepetoId(this.zepetoId, spawnInfo, (character: ZepetoCharacter) => {
            this._npc = character;

            // Dapatkan komponen Animator dari karakter NPC dan atur runtimeAnimatorController-nya ke npcAnimator
            this._npc.GetComponentInChildren<Animator>().runtimeAnimatorController = this.npcAnimator;
        });
    }
}
```



Alur skrip adalah sebagai berikut:

- Start()
  - Dapatkan komponen Animator dari objek NPC dan atur ke Animator Controller yang ditentukan oleh variabel npcAnimator.



3\) Setelah Anda selesai menulis skrip, tambahkan ke objek Lokasi di mana NPC akan dibuat.

4\) Di Inspector, tetapkan Id Zepeto, Animator NPC.

- Animator NPC: Pengontrol animasi NPC.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-CgJYDlgaLNgzETWd9RfCB-20240904-102416.png" size="60" width="499" height="299" position="center" showCaption="false"}



5\) Tekan tombol play untuk menjalankannya dan Anda akan melihat NPC membuat gerakan.

6\) Anda dapat menerapkan ini untuk membuat NPC yang melakukan lebih banyak tindakan selain gerakan dan lompatan.



# Kata-kata di atas NPC



Anda dapat membuat Kanvas di atas kepala NPC, menampilkan gambar atau teks, dan membuatnya berbuih.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-y1YkAff-EjrFNU79j-DES-20240904-102416.png" size="72" width="2344" height="1746" position="center" showCaption="false"}



### Membuat Prefab Kanvas Kata-kata

1\) Buat Hierarchy> UI > Canvas dan ganti namanya menjadi PrefSpeechBubbleCanvas.

- Atur Mode Render ke World Space.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-uk0mM_BrabzsikogLJFqs-20240904-102416.png)



2\) Buat Hierarchy> UI > Gambar sebagai anak dari PrefSpeechBubbleCanvas dan ganti namanya menjadi SpeechBubbleImage.

- Ini adalah gambar yang akan menjadi latar belakang gelembung ucapan.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-u8wdp_2mKNd2U3MIGpE7i-20240904-102416.png "Contoh Pengaturan Gambar")



3\) Buat Hierarki> UI > Teks sebagai anak dari SpeeachBubbleImage dan ganti namanya menjadi SpeeachBubbleText.

- Ini adalah teks di dalam gelembung ucapan.
- Tambahkan komponen Content Size Fitter untuk membuat teks dengan ukuran yang tepat.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-KCY849QEh54QbG-8DA_7t-20240904-102416.png "Contoh Pengaturan Teks")



4\) Setelah selesai, seret ke jendela Proyek untuk menjadikannya Prefab, dan kemudian hapus PrefSpeechBubbleCanvas yang masih ada di Sorotan.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-PpAK7gLrLZb7h0kGbzRWo-20240904-102416.png "Contoh Konfigurasi Prefab")



### Membuat Skrip Gelembung Ucapan NPC



1\) Buat Proyek > Buat > ZEPETO > TypeScript dan ganti namanya menjadi NPCSpeechBubble.

2\) Tulis skrip contoh seperti yang ditunjukkan di bawah ini.

```typescript
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { KnowSockets, SpawnInfo, ZepetoCharacter, ZepetoCharacterCreator } from 'ZEPETO.Character.Controller';
import { Canvas, Camera, Vector3, Object, GameObject } from 'UnityEngine';
import { Text } from 'UnityEngine.UI';

export default class NPCSpeechBubble extends ZepetoScriptBehaviour {

    // ID ZEPETO dari NPC
    public zepetoId: string;
    // Konten dialog yang akan ditampilkan di gelembung bicara
    public speechBubbleText: string;
    // Prefab dari objek game kanvas gelembung bicara
    public speechBubblePrefab: GameObject;
    // Nilai offset sumbu Y dari objek game kanvas gelembung bicara
    public speechBubbleYOffset: number;

    // Objek karakter NPC
    private _npc: ZepetoCharacter;
    // Objek game kanvas gelembung bicara
    private _speechBubbleObject: GameObject;
    // Teks di dalam objek game kanvas gelembung bicara
    private _speechBubbleText: Text;
    // Kanvas gelembung bicara
    private _canvas: Canvas;
    // Kamera Dunia
    private _cachedWorldCamera: Camera;
    
    Start() {
        // Buat instance baru dari SpawnInfo dan atur posisinya serta rotasinya berdasarkan transformasi objek
        const spawnInfo = new SpawnInfo();
        spawnInfo.position = this.transform.position;
        spawnInfo.rotation = this.transform.rotation;

        // Gunakan ZepetoCharacterCreator untuk membuat karakter baru berdasarkan ID ZEPETO dan menetapkannya ke variabel _npc
        ZepetoCharacterCreator.CreateByZepetoId(this.zepetoId, spawnInfo, (character: ZepetoCharacter) => {
            this._npc = character;
            
            // Atur gelembung bicara
            this.SetBubble();
        })
    }

    // Atur gelembung bicara
    SetBubble() {
        // Buat objek game kanvas gelembung bicara secara dinamis
        this._speechBubbleObject = Object.Instantiate(this.speechBubblePrefab) as GameObject;

        // Atur orang tua dari transformasi objek game kanvas gelembung bicara menjadi transformasi NPC.
        this._speechBubbleObject.transform.SetParent(this._npc.transform);
        
        // Atur posisi objek game kanvas gelembung bicara di atas kepala NPC
        this._speechBubbleObject.transform.position = Vector3.op_Addition(this._npc.GetSocket(KnowSockets.HEAD_UPPER).position, new Vector3(0, this.speechBubbleYOffset,0));

        // Atur teks di dalam gelembung bicara
        this._speechBubbleText = this._speechBubbleObject.GetComponentInChildren<Text>();
        this.SetBubbleText(this.speechBubbleText);

        this._canvas = this._speechBubbleObject.GetComponent<Canvas>();
        this._cachedWorldCamera = Object.FindObjectOfType<Camera>();
        this._canvas.worldCamera = this._cachedWorldCamera;
    }

    // Buka kanvas gelembung bicara dan atur teks
    SetBubbleText(bubbleText: string) {
        this._speechBubbleObject.SetActive(true);
        this._speechBubbleText.text = bubbleText;
    }

    private Update() {
        if (this._canvas != null) {
            this.UpdateCanvasRotation();
        }
    }

    // Perbarui rotasi kanvas gelembung bicara agar menghadap kamera
    private UpdateCanvasRotation() {
        this._canvas.transform.LookAt(this._cachedWorldCamera.transform);
        this._canvas.transform.Rotate(0, 180, 0);
    }

}
```



Alur skrip adalah sebagai berikut:

- Mulai()
  - Panggil fungsi kustom SetBubble().
- SetBubble()
  - Buat kanvas gelembung bicara (speechBubblePrefab) dan posisikan gelembung bicara yang dibuat di atas kepala NPC
  - Panggil fungsi kustom SetBubbleText() untuk mengatur teks di dalam gelembung bicara.
- SetBubbleText()
  - Mengaktifkan kanvas gelembung bicara NPC (\_speechBubbleObject).
  - Menampilkan string yang diberikan sebagai parameter (bubbleText) di dalam gelembung bicara.
- Perbarui()
  - Panggil fungsi kustom UpdateCanvasRotation() untuk memutar kanvas agar sesuai dengan kamera.



3\) Setelah Anda selesai menulis skrip, tambahkan ke objek Lokasi di mana NPC akan dibuat.

4\) Di Inspector, tetapkan Zepeto Id, Teks Balon Bicara, Prefab Balon Bicara, dan Offset Y Balon Bicara.

- Teks Balon Bicara: Variabel ini menyimpan dialog yang akan diucapkan karakter NPC dalam balon bicara. Dalam contoh kami, kami menyimpan dialog berikut: "Halo Dunia".
- Prefab Balon Bicara: Variabel ini menyimpan prefab untuk GameObject Kanvas Balon Bicara.
- Offset Y Balon Bicara: Variabel ini menyimpan nilai offset sumbu-y untuk GameObject Kanvas Balon Bicara. Ini memungkinkan Anda untuk menyesuaikan jarak antara karakter dan balon bicara saat Anda menempatkan balon bicara di atas kepala karakter.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-gIn4E4c0m0HetSALlRzLb-20240904-102416.png" size="76" width="499" height="342" position="center" caption="Contoh Layar Pengaturan Skrip" showCaption="true"}

5\) tekan tombol play untuk mengeksekusi, dan Anda akan melihat balon bicara mengapung di atas kepala NPC.



# Berinteraksi dengan NPC



Anda dapat menerapkan banyak konten menyenangkan dengan berinteraksi dengan NPC.

Dalam panduan ini, kami akan menggunakan contoh untuk menerapkan gelembung ucapan yang berubah saat NPC didekati.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-rlzfSSbfFzCHSTypmkC5v-20240904-102419.gif" size="42" width="800" height="639" position="center" showCaption="false"}



### Mengatur Collider



1\) Tambahkan komponen Collider ke objek Anda untuk berinteraksi dengan NPC dan periksa isTrigger.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-fLpIWDpR24sxEAh5j_GSL-20240904-102416.png)



2\) Ubah ukuran Collider agar pemain dapat berinteraksi dengan NPC.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-l5kXKnIsuXNjgVTvjUdSx-20240904-102416.png)



### Membuat Skrip Interaksi NPC



1\) Buat Proyek > Buat > ZEPETO > TypeScript dan ganti namanya menjadi NPCInteraction.

2\) Tulis skrip contoh seperti yang ditunjukkan di bawah ini.

```typescript
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { KnowSockets, SpawnInfo, ZepetoCharacter, ZepetoCharacterCreator, ZepetoPlayers } from 'ZEPETO.Character.Controller';
import { Canvas, Camera, Vector3, Object, GameObject, Collider } from 'UnityEngine';
import { Text } from 'UnityEngine.UI';

export default class NPCInteraction extends ZepetoScriptBehaviour {

    // ID ZEPETO dari NPC
    public zepetoId: string;
    // Konten dialog yang akan ditampilkan di gelembung bicara
    public speechBubbleText: string;

    public changedSpeechBubbleText: string;
    // Prefab dari objek game kanvas gelembung bicara
    public speechBubblePrefab: GameObject;
    // Nilai offset sumbu y dari objek game kanvas gelembung bicara
    public speechBubbleYOffset: number;

    // Objek karakter lokal
    private _zepetoCharacter: ZepetoCharacter;
    // Objek karakter NPC
    private _npc: ZepetoCharacter;
    // Objek game kanvas gelembung bicara
    private _speechBubbleObject: GameObject;
    // Teks di dalam objek game kanvas gelembung bicara
    private _speechBubbleText: Text;
    // Kanvas gelembung bicara
    private _canvas: Canvas;
    // Kamera Dunia
    private _cachedWorldCamera: Camera;
    
    Start() {
        // Buat instance baru dari SpawnInfo dan atur posisinya serta rotasinya berdasarkan transform objek
        const spawnInfo = new SpawnInfo();
        spawnInfo.position = this.transform.position;
        spawnInfo.rotation = this.transform.rotation;

        // Gunakan ZepetoCharacterCreator untuk membuat karakter baru berdasarkan ID ZEPETO dan menetapkannya ke variabel _npc
        ZepetoCharacterCreator.CreateByZepetoId(this.zepetoId, spawnInfo, (character: ZepetoCharacter) => {
            this._npc = character;
            
            // Atur gelembung bicara
            this.SetBubble();
        })

        ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {
            this._zepetoCharacter = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
        });
    }

    // Periksa apakah karakter Pemain memasuki collider
    OnTriggerEnter(collider: Collider) {
        if (this._zepetoCharacter == null || collider.gameObject != this._zepetoCharacter.gameObject) {
            return;
        }
        this.SetBubbleText(this.changedSpeechBubbleText);
    }

    OnTriggerExit(collider: Collider) {
        if (this._zepetoCharacter == null || collider.gameObject != this._zepetoCharacter.gameObject) {
            return;
        }
        this.SetBubbleText(this.speechBubbleText);
    }


    // Atur gelembung bicara
    SetBubble() {
        // Buat objek game kanvas gelembung bicara secara dinamis
        this._speechBubbleObject = Object.Instantiate(this.speechBubblePrefab) as GameObject;

        // Atur parent dari transform objek game kanvas gelembung bicara menjadi transform NPC.
        this._speechBubbleObject.transform.SetParent(this._npc.transform);
        
        // Atur posisi objek game kanvas gelembung bicara di atas kepala NPC
        this._speechBubbleObject.transform.position = Vector3.op_Addition(this._npc.GetSocket(KnowSockets.HEAD_UPPER).position, new Vector3(0, this.speechBubbleYOffset,0));

        // Atur teks di dalam gelembung bicara
        this._speechBubbleText = this._speechBubbleObject.GetComponentInChildren<Text>();
        this.SetBubbleText(this.speechBubbleText);
        
        this._canvas = this._speechBubbleObject.GetComponent<Canvas>();
        this._cachedWorldCamera = Object.FindObjectOfType<Camera>();
        this._canvas.worldCamera = this._cachedWorldCamera;
    }

    // Buka kanvas gelembung bicara dan atur teks
    SetBubbleText(bubbleText: string) {
        this._speechBubbleObject.SetActive(true);
        this._speechBubbleText.text = bubbleText;
    }

    private Update() {
        if (this._canvas != null) {
            this.UpdateCanvasRotation();
        }
    }

    // Perbarui rotasi kanvas gelembung bicara agar menghadap kamera
    private UpdateCanvasRotation() {
        this._canvas.transform.LookAt(this._cachedWorldCamera.transform);
        this._canvas.transform.Rotate(0, 180, 0);
    }
    
}
```



Alur skrip adalah sebagai berikut:

- OnTriggerEnter(), OnTriggerExit()
  - Ketika pemicu terdeteksi dengan memasuki area collider, panggil fungsi kustom SetBubbleText() untuk mengatur teks di dalam gelembung bicara menjadi changedSpeechBubbleText.
  - Ketika meninggalkan area collider, panggil fungsi kustom SetBubbleText() untuk mengatur teks di dalam gelembung bicara menjadi speechBubbleText.



3\) Setelah Anda selesai menulis skrip, tambahkan ke objek Lokasi di mana NPC akan dibuat.

4\) Di Inspector, tetapkan Zepeto Id, Teks Gelembung Bicara, Prefab Gelembung Bicara, Offset Y Gelembung Bicara, dan Gelembung Bicara yang Diubah.

- Teks Gelembung Bicara: Variabel ini menyimpan dialog yang akan diucapkan karakter NPC di dalam gelembung bicara. Dalam contoh kami, kami menyimpan dialog berikut: "Halo Dunia".
- Prefab Gelembung Bicara: Variabel ini menyimpan prefab untuk GameObject Kanvas Gelembung Bicara.
- Offset Y Gelembung Bicara: Variabel ini menyimpan nilai offset sumbu-y untuk GameObject Kanvas Gelembung Bicara. Ini memungkinkan Anda untuk menyesuaikan jarak antara karakter dan gelembung bicara saat menempatkan gelembung bicara di atas kepala karakter.
- Gelembung Bicara yang Diubah: Menyimpan dialog yang akan ditampilkan di gelembung bicara NPC ketika pemain memasuki collider NPC.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-WtOJ3nQKqkxWUSPkqN65j-20240904-102416.png" size="82" width="502" height="189" position="center" caption="Contoh Layar Pengaturan Skrip" showCaption="true"}



5\) tekan play untuk mengeksekusi, dan ketika pemain mendekati NPC, teks di gelembung bicara akan berubah.



### Terapkan interaksi NPC



Untuk membuat format dialog, buat UI menggunakan panel.

Berikut adalah contoh dialog sederhana yang terdiri dari panel dan tombol.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-qQe1Xx8mTUbOapkLXU_-Z-20240904-102416.png" size="78" width="1452" height="910" position="center" showCaption="false"}



Ini adalah contoh skrip yang membuka dialog saat berinteraksi dengan NPC dan memprosesnya saat setiap tombol ditekan.

Terapkan ini untuk menerapkan konten yang menarik.

```typescript
import { GameObject, HumanBodyBones, Object, Collider } from 'UnityEngine';
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';
import { Button } from 'UnityEngine.UI';
import { ZepetoCharacter, ZepetoPlayers } from "ZEPETO.Character.Controller";

export default class NPCDialogInteraction extends ZepetoScriptBehaviour {

    public npcDialogCanvas: GameObject;
    public yesButton: Button;
    public noButton: Button;

    private _zepetoCharacter: ZepetoCharacter;

    Start() {

        ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(()=>{
            this._zepetoCharacter = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;
        });
        
        // Dialog - Pilih Ya
        this.yesButton.onClick.AddListener(() => {
            console.log("ya")
            this.npcDialogCanvas.SetActive(false);
        });

        // Dialog - Pilih Tidak
        this.noButton.onClick.AddListener(() => {
            console.log("tidak")
            this.npcDialogCanvas.SetActive(false);
        });

    }

    // Periksa jika karakter Pemain memasuki collider
    OnTriggerEnter(collider: Collider) {
        if (this._zepetoCharacter == null || collider.gameObject != this._zepetoCharacter.gameObject) {
            return;
        }
        this.npcDialogCanvas.SetActive(true);
    }

    OnTriggerExit(collider: Collider) {
        if (this._zepetoCharacter == null || collider.gameObject != this._zepetoCharacter.gameObject) {
            return;
        }
        this.npcDialogCanvas.SetActive(false);
    }

}
```

