BUAT DUNIAMU
Pemain & Karakter: Dasar
ZEPETO Players
21 mnt
zepetoplayers adalah kelas manajer (singleton) yang dirancang untuk mengontrol baik pemain zepeto maupun karakter zepeto dengan menambahkan zepetoplayers ke dalam sebuah adegan, anda dapat membuat, menghapus, dan memanipulasi pemain zepeto zepetoplayer mewakili sebuah instance individu dari karakter zepeto yang digunakan untuk mengelola baik pemain yang anda kendalikan secara langsung di dunia multiplayer maupun pemain lainnya setiap zepetoplayer yang dibuat di dunia multiplayer diberikan id sesi unik dan dikelola menggunakan id sesi ini karena zepetoplayer memiliki atribut zepetocharacter, ia dapat dikendalikan menggunakan fungsi yang terkait dengan zepetocharacter ada tiga jenis zepetoplayer zepetoplayer deskripsi pemain lokal mewakili instansi karakter zepeto yang dikendalikan langsung oleh pengguna lokal \ dilengkapi dengan komponen pengendali karakter/kamera zepeto pemain jaringan (pemain jarak jauh) instansi karakter zepeto yang dapat dimuat dan digunakan dalam konten multiplay \ tidak memiliki komponen pengendali karakter/kamera zepeto yang terpasang pemain bot instansi karakter zepeto untuk konten multiplay, tetapi dikendalikan oleh bot alih alih pengguna nyata digunakan sebagai pengganti saat memulai dunia multiplayer dengan pemain yang tidak mencukupi atau jika seorang pemain meninggalkan permainan selama bermain \ tidak memiliki komponen pengendali karakter/kamera zepeto yang terpasang silakan merujuk ke panduan berikut \[ zepeto player docid tvoiujhwojg5dz1vw9xw ] \[ panduan pembuatan pemain bot docid\ vhgs710hfyx8gx8fmp5ih ] zepetocharacter adalah unit instance dasar dari karakter zepeto yang dapat dimuat dan dikendalikan di world scene zepetocharacter memiliki penampilan avatar yang dibuat melalui aplikasi zepeto silakan merujuk ke panduan berikut \[ karakter zepeto docid\ xz6zljtc hierlbbdaort ] menambahkan zepetoplayers di jendela hierarchy, pilih zepeto → tab zepetoplayers anda sekarang dapat menambahkannya ke adegan anda perhatikan bahwa hanya menambahkan zepetoplayers tidak membawa pemain zepeto ke dalam adegan anda perlu menerapkan skrip menggunakan api pembuatan karakter dari zepetoplayers jika anda ingin dengan cepat membuat dan mencoba hanya pemain lokal dalam sebuah adegan, silakan merujuk ke panduan silakan merujuk ke panduan berikut \[ membuat karakter zepeto docid 6xbdpw8hvdwop3dxh17ww ] untuk contoh tentang cara menampilkan nama dan foto profil pemain zepeto, lihat panduan berikut silakan merujuk ke panduan berikut \[ informasi pengguna docid\ n6zk okq6 dc06yvvqyk ] api pemain zepeto jika anda tertarik dengan api zepetoplayers, silakan merujuk ke dokumentasi silakan merujuk ke panduan berikut \[ api zepeto character controller ] panduan ini terutama mencakup contoh penggunaan pemain zepeto dalam skenario multipemain mengimplementasikan sinkronisasi posisi multiplay menggunakan pemain zepeto dalam dunia pemain tunggal, hanya pemain lokal yang perlu dibuat dan karena hanya pemain lokal yang muncul di layar, sinkronisasi tidak diperlukan namun, dalam dunia multiplay, tidak hanya pemain lokal yang anda kendalikan secara langsung tetapi juga pemain lain, yang disebut pemain jaringan, perlu ditampilkan di layar setiap tindakan pemain jaringan bergerak, melompat, dan melakukan gerakan tertentu harus muncul identik di layar anda proses ini disebut sinkronisasi tanpa menerapkan skrip sinkronisasi, anda tidak akan dapat melihat penampilan atau gerakan pemain jaringan dalam dunia multiplay tanpa sinkronisasi, satu satunya cara untuk mengetahui apakah klien lain telah masuk ke ruangan adalah melalui tombol beranda langkah 1 menyiapkan lingkungan multiplay disarankan untuk memulai dengan memahami pengaturan dasar dan konsep multiplay melalui video tutorial multiplay silakan merujuk ke panduan berikut \[ tutorial bermain ganda docid\ lyyby8vxbmg toab1ufuw ] \[ bermain ganda docid\ cvcg580umg hwv8qbgm0p ] langkah 2 menampilkan pemain lain di layar anda pemain lokal anda diperlakukan sebagai pemain jaringan di perangkat orang lain ini berarti bahwa bahkan pemain lokal anda harus mengirim informasi ke server untuk sinkronisasi semua pemain yang terhubung ke dunia multiplay harus berbagi informasi mereka semua klien yang terhubung ke ruangan multiplay berbagi data status ruangan multiplay data status ruangan ini mengikuti skema yang ditentukan dalam schemas json (silakan anggap skema sebagai struktur data) dalam panduan ini, anda akan menyinkronkan posisi pemain melalui data status ruangan oleh karena itu, definisikan skema dalam schemas json yang dapat mewakili data posisi untuk setiap pemain schema json { "state" {"players" {"map" "player"}}, "player" {"sessionid" "string","zepetouserid" "string","transform" "transform","state" "number","substate" "number"}, "transform" {"position" "vector3","rotation" "vector3"}, "vector3" {"x" "number","y" "number","z" "number"} } silakan merujuk ke panduan berikut \[ status ruangan multiplay docid\ z4 2g1uc90um58zijzgf ] 👍 tips simpan semua informasi yang harus dibagikan oleh server dan semua klien di status ruangan multiplay simpan data individu untuk setiap pemain, seperti level, poin pengalaman, skor, dll , menggunakan datastorage skrip server dapat mengenali ketika pemain lain telah memasuki ruangan dan dapat mengirimkan informasi itu ke klien untuk memuat pemain tersebut ke dalam adegan langkah 2 1 skrip server dasar ketika seorang pemain memasuki ruangan dunia multiplay, onjoin() dipanggil dalam skrip server, tambahkan informasi tentang pemain yang terhubung ke pemain ruang status juga, ketika seorang pemain keluar dari ruangan, onleave() dipanggil skrip server akan menghapus informasi pemain yang keluar dari pemain ruang status import {sandbox, sandboxoptions, sandboxplayer} from "zepeto multiplay"; import {player} from "zepeto multiplay schema"; export default class extends sandbox { oncreate(options sandboxoptions) { } async onjoin(client sandboxplayer) { const player = new player(); player sessionid = client sessionid; if (client userid) { player zepetouserid = client userid; } // kelola objek pemain menggunakan sessionid, nilai kunci unik dari objek klien // klien dapat memeriksa informasi tentang objek pemain yang ditambahkan dengan menambahkan acara add onadd ke objek pemain this state players set(client sessionid, player); } async onleave(client sandboxplayer, consented? boolean) { this state players delete(client sessionid); } } langkah 2 2 skrip klien dasar saat membuat dunia multiplay, skrip klien diperlukan untuk berkomunikasi dengan server di bawah ini adalah contoh skrip klien dasar untuk permainan multiplayer di sisi klien, kami mengelola data pemain yang akan ditampilkan di klien kami menggunakan currentplayers struktur data peta baris kode yang penting diilustrasikan di bawah ini zepetoplayers instance createplayerwithuserid(sessionid, player zepetouserid, spawninfo, islocal); ketika klien menerima informasi pemain dari status ruang server dan seorang pemain baru bergabung ke ruang, sebuah id sesi diberikan jika id sesi dari pemain yang sedang dibuat cocok dengan id sesi kita sendiri, pemain tersebut dianggap lokal dalam hal ini, pemain akan diinstansiasi dengan islocal = true , yang menunjukkan bahwa itu adalah pemain lokal selanjutnya, pemain yang bukan lokal dibuat dengan islocal = false ini memastikan bahwa penampilan semua pemain, baik lokal maupun non lokal, ditampilkan di layar import {zepetoscriptbehaviour} from 'zepeto script' import {zepetoworldmultiplay} from 'zepeto world' import {room, roomdata} from 'zepeto multiplay' import {player, state, vector3} from 'zepeto multiplay schema' import {characterstate, spawninfo, zepetoplayers, zepetoplayer, characterjumpstate} from 'zepeto character controller' import as unityengine from "unityengine"; export default class multiplayclientcode extends zepetoscriptbehaviour { public multiplay zepetoworldmultiplay; private room room; private currentplayers map\<string, player> = new map\<string, player>(); private zepetoplayer zepetoplayer; private start() { this multiplay roomcreated += (room room) => { this room = room; }; this multiplay roomjoined += (room room) => { room onstatechange += this onstatechange; }; } private onstatechange(state state, isfirst boolean) { // ketika event onstatechange pertama diterima, snapshot status penuh dicatat if (isfirst) { // \[charactercontroller] (lokal) dipanggil ketika instance pemain sepenuhnya dimuat di scene zepetoplayers instance onaddedlocalplayer addlistener(() => { const myplayer = zepetoplayers instance localplayer zepetoplayer; this zepetoplayer = myplayer; }); // \[charactercontroller] (lokal) dipanggil ketika instance pemain sepenuhnya dimuat di scene zepetoplayers instance onaddedplayer addlistener((sessionid string) => { const islocal = this room sessionid === sessionid; if (!islocal) { const player player = this currentplayers get(sessionid); } }); } let join = new map\<string, player>(); let leave = new map\<string, player>(this currentplayers); state players foreach((sessionid string, player player) => { if (!this currentplayers has(sessionid)) { join set(sessionid, player); } leave delete(sessionid); }); // \[roomstate] buat instance pemain untuk pemain yang masuk ke ruangan join foreach((player player, sessionid string) => this onjoinplayer(sessionid, player)); // \[roomstate] hapus instance pemain untuk pemain yang keluar dari ruangan leave foreach((player player, sessionid string) => this onleaveplayer(sessionid, player)); } private onjoinplayer(sessionid string, player player) { console log(`\[onjoinplayer] pemain sessionid ${sessionid}`); this currentplayers set(sessionid, player); // buat pemain const islocal = this room sessionid === player sessionid; zepetoplayers instance createplayerwithuserid(sessionid, player zepetouserid, new spawninfo(), islocal); } private onleaveplayer(sessionid string, player player) { console log(`\[onremove] pemain sessionid ${sessionid}`); this currentplayers delete(sessionid); zepetoplayers instance removeplayer(sessionid); } } sekarang, ketika seorang pemain masuk, anda dapat mengonfirmasi bahwa karakter zepeto dibuat di layar anda tetapi, gerakan pemain belum tercermin di layar mari kita lanjutkan ke penyelarasan posisi berikutnya langkah 3 menyelaraskan dengan mengambil informasi pemain lain untuk penyelarasan, setiap kali seorang pemain bergerak atau melakukan tindakan, mereka harus mengirimkan perubahan status mereka ke server mengirim pesan yang berisi perubahan status mereka ke server dilakukan melalui komunikasi pesan ruangan ketika server menerima pesan tentang perubahan status pemain, server memperbarui status ruangan silakan merujuk ke panduan berikut \[ proses koneksi ruangan docid\ dxdbn6wvi82ag wdc1thr ] misalnya, mari kita anggap bahwa pemain lokal anda bernama b ketika pemain jaringan a bergabung dengan ruangan, mereka diinstansiasi pada koordinat x 0, y 0, z 0 jika pemain a bergerak ke posisi x 10, y 0, z 0, b tidak memiliki cara nyata untuk mengetahui bahwa a sedang bergerak ini karena keduanya dioperasikan secara lokal di perangkat terpisah, sehingga di klien yang terpisah dengan demikian, orang yang mengendalikan a perlu mengkomunikasikan gerakannya ke server melalui pesan ruangan setelah server menerima informasi ini, ia memberitahu semua orang yang hadir di ruangan tentang posisi a secara real time dengan cara ini, b akhirnya menyadari bahwa a sedang bergerak agar server dapat memberi tahu pemain lain, ada dua metode menggunakan siaran pesan ruangan memperbarui status ruangan, kemudian meminta klien untuk mengambil dan menerapkan status ruangan panduan ini menggunakan metode kedua untuk memperbarui status ruangan mengingat bahwa pemain zepeto yang dimuat ke dalam adegan memiliki atribut karakter zepeto, anda dapat menggunakan fungsi karakter zepeto untuk memerintahkan gerakan ke lokasi tertentu atau memulai lompatan agar klien b dapat memvisualisasikan gerakan a ke x 10, y 0, z 0, pendekatan yang paling intuitif adalah menggunakan movetoposition() fungsi ini akan memindahkan pemain ke posisi terbaru a yang diterima dari server tidak hanya perubahan posisi, tetapi juga gerakan, penggunaan keterampilan, pengumpulan item, dan semua perubahan status memerlukan komunikasi server klien untuk sinkronisasi anda perlu menerapkan sinkronisasi untuk menjaga setiap tindakan tetap harmonis di seluruh jaringan 👍 ringkasan konsep sinkronisasi ketika pemain lokal mengalami perubahan status, mereka mengirimkannya ke server menggunakan pesan ruangan server memberi tahu semua pemain lain kecuali pemain lokal tentang perubahan status setelah menerima pesan perubahan status, kode klien memperbarui status pemain yang mengirim pesan tersebut langkah 3 1 skrip server dengan sinkronisasi posisi yang selesai dalam skrip server dasar, implementasi tambahan diperlukan untuk memperbarui status ruangan setiap kali pesan tentang perubahan status dari klien pemain lokal diterima import {sandbox, sandboxoptions, sandboxplayer} from "zepeto multiplay"; import {player, transform, vector3} from "zepeto multiplay schema"; export default class extends sandbox { constructor() { super(); } oncreate(options sandboxoptions) { // dipanggil ketika objek ruangan dibuat // tangani inisialisasi status atau data objek ruangan 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; if (player) { player transform = transform; } }); this onmessage("onchangedstate", (client, message) => { const player = this state players get(client sessionid); if (player) { player state = message state; player substate = message substate; // pengendali karakter v2 } }); } async onjoin(client sandboxplayer) { // buat objek pemain yang didefinisikan dalam schemas json dan atur nilai awal console log(`\[onjoin] sessionid ${client sessionid}, userid ${client userid}`) const player = new player(); player sessionid = client sessionid; if (client userid) { player zepetouserid = client userid; } // kelola objek pemain menggunakan sessionid, nilai kunci unik dari objek klien // klien dapat memeriksa informasi tentang objek pemain yang ditambahkan dengan menambahkan acara add onadd ke objek pemain this state players set(client sessionid, player); } async onleave(client sandboxplayer, consented? boolean) { // dengan mengatur allowreconnection, dimungkinkan untuk mempertahankan koneksi untuk sirkuit, tetapi bersihkan segera dalam panduan dasar // klien dapat memeriksa informasi tentang objek pemain yang dihapus dengan menambahkan acara add onremove ke objek pemain this state players delete(client sessionid); } } langkah 3 2 skrip klien dengan sinkronisasi posisi yang selesai implementasi kunci dalam skrip klien dasar adalah secara otomatis panggil onstatechange ketika status ruangan server berubah menggunakan sendmessageloop(0 04) fungsi, kirim posisi pemain lokal dan informasi status lompatan karakter ke server setiap 0,04 detik import {zepetoscriptbehaviour} from 'zepeto script' import {zepetoworldmultiplay} from 'zepeto world' import {room, roomdata} from 'zepeto multiplay' import {player, state, vector3} from 'zepeto multiplay schema' import {characterstate, spawninfo, zepetoplayers, zepetoplayer, characterjumpstate} from 'zepeto character controller' import as unityengine from "unityengine"; export default class clientstarterv2 extends zepetoscriptbehaviour { public multiplay zepetoworldmultiplay; private room room; private currentplayers map\<string, player> = new map\<string, player>(); private zepetoplayer zepetoplayer; private start() { this multiplay roomcreated += (room room) => { this room = room; }; this multiplay roomjoined += (room room) => { room onstatechange += this onstatechange; }; this startcoroutine(this sendmessageloop(0 04)); } // kirim transformasi karakter lokal ke server pada interval waktu yang dijadwalkan private sendmessageloop(tick number) { while (true) { yield new unityengine waitforseconds(tick); if (this room != null && this room isconnected) { const hasplayer = zepetoplayers instance hasplayer(this room sessionid); if (hasplayer) { const character = zepetoplayers instance getplayer(this room sessionid) character; this sendtransform(character transform); this sendstate(character currentstate); } } } } private onstatechange(state state, isfirst boolean) { // ketika event onstatechange pertama diterima, snapshot status penuh dicatat if (isfirst) { // \[charactercontroller] (lokal) dipanggil ketika instance pemain sepenuhnya dimuat di scene zepetoplayers instance onaddedlocalplayer addlistener(() => { const myplayer = zepetoplayers instance localplayer zepetoplayer; this zepetoplayer = myplayer; }); // \[charactercontroller] (lokal) dipanggil ketika instance pemain sepenuhnya dimuat di scene zepetoplayers instance onaddedplayer addlistener((sessionid string) => { const islocal = this room sessionid === sessionid; if (!islocal) { const player player = this currentplayers get(sessionid); // \[roomstate] dipanggil setiap kali status instance pemain diperbarui player onchange += (changevalues) => this onupdateplayer(sessionid, player); } }); } let join = new map\<string, player>(); let leave = new map\<string, player>(this currentplayers); state players foreach((sessionid string, player player) => { if (!this currentplayers has(sessionid)) { join set(sessionid, player); } leave delete(sessionid); }); // \[roomstate] buat instance pemain untuk pemain yang masuk ke ruangan join foreach((player player, sessionid string) => this onjoinplayer(sessionid, player)); // \[roomstate] hapus instance pemain untuk pemain yang keluar dari ruangan leave foreach((player player, sessionid string) => this onleaveplayer(sessionid, player)); } private onjoinplayer(sessionid string, player player) { console log(`\[onjoinplayer] pemain sessionid ${sessionid}`); this currentplayers set(sessionid, player); const spawninfo = new spawninfo(); const position = this parsevector3(player transform position); const rotation = this parsevector3(player transform rotation); spawninfo position = position; spawninfo rotation = unityengine quaternion euler(rotation); const islocal = this room sessionid === player sessionid; zepetoplayers instance createplayerwithuserid(sessionid, player zepetouserid, spawninfo, islocal); } private onleaveplayer(sessionid string, player player) { console log(`\[onremove] pemain sessionid ${sessionid}`); this currentplayers delete(sessionid); zepetoplayers instance removeplayer(sessionid); } private onupdateplayer(sessionid string, player player) { const position = this parsevector3(player transform position); const zepetoplayer = zepetoplayers instance getplayer(sessionid); var movedir = unityengine vector3 op subtraction(position, zepetoplayer character transform position); movedir = new unityengine vector3(movedir x, 0, movedir z); if (movedir magnitude < 0 05) { if (player state === characterstate moveturn) return; zepetoplayer character stopmoving(); } else { zepetoplayer character movecontinuously(movedir); } if (player state === characterstate jump) { if (zepetoplayer character currentstate !== characterstate jump) { zepetoplayer character jump(); } if (player substate === characterjumpstate jumpdouble) { zepetoplayer character doublejump(); } } } private sendtransform(transform unityengine transform) { const data = new roomdata(); const pos = new roomdata(); pos add("x", transform localposition x); pos add("y", transform localposition y); pos add("z", transform localposition z); data add("position", pos getobject()); const rot = new roomdata(); rot add("x", transform localeulerangles x); rot add("y", transform localeulerangles y); rot add("z", transform localeulerangles z); data add("rotation", rot getobject()); this room send("onchangedtransform", data getobject()); } private sendstate(state characterstate) { const data = new roomdata(); data add("state", state); if(state === characterstate jump) { data add("substate", this zepetoplayer character motionv2 currentjumpstate); } this room send("onchangedstate", data getobject()); } private parsevector3(vector3 vector3) unityengine vector3 { return new unityengine vector3 ( vector3 x, vector3 y, vector3 z ); } } 👍 tips panduan ini hanya menerapkan sinkronisasi posisi sinkronisasi gerakan, sinkronisasi objek, dll , belum diterapkan prinsipnya sama untuk semua, tetapi proses mengirim dan menerima pesan ruang pada setiap momen yang diperlukan adalah hal yang penting jika anda ingin menerapkan sinkronisasi dengan lebih nyaman, pertimbangkan untuk menggunakan modul sinkronisasi multiplay