TUTORIAL
Tutorial Bermain Ganda
15mnt
proyek contoh 📘 contoh multiplay https //github com/naverz/zepeto multiplay example https //github com/naverz/zepeto multiplay example ringkasan ringkasan dari membuat server multiplay hingga klien, siapkan lingkungan yang diperlukan untuk mengembangkan dunia multiplay kesulitan menengah waktu yang diperlukan 1 jam bagian 1 menginstal multiplay dari membuat server multiplay hingga klien, siapkan lingkungan yang diperlukan untuk mengembangkan dunia multiplay https //www youtube com/watch?v=s68b1tma a8 https //www youtube com/watch?v=s68b1tma a8 bagian 2 menulis logika dunia pelajari tentang skema yang diperlukan untuk komunikasi antara server dan klien, dan definisikan jenis skema dan status ruangan https //www youtube com/watch?v=tfky rabov0 https //www youtube com/watch?v=tfky rabov0 harap dicatat bahwa skrip server yang digunakan dalam video, yang mencakup konten terkait hashcode, tidak lagi didukung oleh karena itu, kecualikan kode berikut saat menulis if (client hashcode) { 	player zepetohash = client hashcode; } bagian 3 menulis logika dunia 2 tulis logika dunia yang diperlukan untuk menyinkronkan dari lokasi pemain ke keluaran pemain https //www youtube com/watch?v=h92gd2g9dhm https //www youtube com/watch?v=h92gd2g9dhm bagian 4 menjalankan server dan menghubungkan ke multiplay jalankan server dan hubungkan ke multiplay https //www youtube com/watch?v=fmk6jnlsjja https //www youtube com/watch?v=fmk6jnlsjja bagian 5 skrip schemas json schemas json { "state" {"players" {"map" "pemain"}}, "player" {"sessionid" "string","zepetouserid" "string","transform" "transformasi","state" "number","substate" "number"}, "transform" {"position" "vektor3","rotation" "vektor3"}, "vector3" {"x" "number","y" "number","z" "number"} } kode server index ts import {sandbox, sandboxoptions, sandboxplayer} from "zepeto multiplay"; import {datastorage} from "zepeto multiplay datastorage"; import {player, transform, vector3} from "zepeto multiplay schema"; export default class extends sandbox { storagemap\ map\<string,datastorage> = new map\<string, datastorage>(); constructor() { super(); } oncreate(options sandboxoptions) { // dipanggil saat objek ruang dibuat // tangani status atau inisialisasi data objek ruang 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; // pengontrol 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; } // \[datastorage] memuat datastorage pemain yang masuk const storage datastorage = client loaddatastorage(); this storagemap set(client sessionid,storage); let visit cnt = await storage get("visitcount") as number; if (visit cnt == null) visit cnt = 0; console log(`\[onjoin] jumlah kunjungan ${client sessionid} ${visit cnt}`) // \[datastorage] perbarui jumlah kunjungan pemain dan kemudian simpan storage await storage set("visitcount", ++visit cnt); // 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); } ontick(deltatime number) void { // dipanggil berulang kali pada setiap waktu yang ditetapkan di server, dan acara interval tertentu dapat dikelola menggunakan deltatime } async onleave(client sandboxplayer, consented? boolean) { 	 // dengan mengatur allowreconnection, dimungkinkan untuk mempertahankan koneksi untuk sirkuit, tetapi segera membersihkan 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); } } kode klien clientstarter ts 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 ); } }