Multiplayer Avatar Color

Hello, I’m setting up the color of my avatar using the PlayerColor.ts as a reference. Currently I’m able to update the color of the avatar, but I’d like to ask how can I replicate the color that my user has selected to the rest of the users. Thanks in advance.

Original Post on Discord

by user 939271426349862963

Hello @VicDev the PlayerColor script’s purpose is to uniquely color each connected user with a stable color (based on their networking connection id).

I’m not how familiar you are with coding but you can network the selected color in a custom script if you need different behaviour:

But maybe it would be good to add that feature to the PlayerColor component :slightly_smiling_face:

let me know how it goes

Thanks for your help. I’m an experienced c# dev, but a total noob with TS and JS. I’ve implemented the IModel interface on my class and I’m trying to send the gameobject this way: this.context.connection.send(this.connId, this.gameObject as IModel, SendQueue.Immediate);

by user 939271426349862963

Unfortunately I’m receiving this error message:

uncaught range error: maximum call stack size exceeded
/node_modules/.vite/deps/chunk-BYWKJQSH.js?cf5a31f5:5110:14
at JSON.stringify ()
at Mesh.toJSON(https:192.168.3.8:3000/…

by user 939271426349862963

Ah ok so the IModel is your data model to send. It just forces you to implement a guid. But you would normally just add it to a new type like:

export class MyDataToSend implement IModel {
  guid : string;
  myColor:number;
}

the guid in your case would be the user’s connection id most likely. this.context.connection.connectionId

Thanks for your response. I’ve created my AvatarColorUpdate type. Before sending the message, I’m converting my THREE.Color into a number with bit shifting. Now the error message is not being displayed anymore, but the color isn’t being updated over the network
const packedColor = ((col.r * 255) << 16) | ((col.g * 255) << 8) | (col.b * 255);
let myData = new AvatarColorUpdate(this.connId, packedColor);

by user 939271426349862963

Do you alos subscribe to the event? Insteads of “this.connId” you need to define a event key (e.g “change-player-color”) and then listen to the event to apply it (if(myData.guid === this.playerGuid) ...)

see Networking | Needle Engine Documentation

        this.startCoroutine(this.waitForConnection());
        this.context.connection.beginListen("avatarColorUpdate", (data) => {
            let rdata = data as AvatarColorUpdate;
            console.log("===1==="+rdata.connId+"_"+rdata.color);
            console.log("===2==="+rdata.guid+"_"+rdata.myColor);
            console.log('received: ${JSON.stringify(data)}');
        });

by user 939271426349862963

I wrote the code above on the onEnable method, and I’m sending my information when a button is clicked: ```Typescript
let myData = new AvatarColorUpdate(this.connId, packedColor);
console.log("send: “+myData.connId+” and "+myData.color);
this.context.connection.send(“avatarColorUpdate”, myData, SendQueue.Immediate);


*by user 939271426349862963*

but not sure why I’m not receiving the data on the listener

by user 939271426349862963

Are you connected to a room? (using the SyncedRoom component)

I think I do

by user 939271426349862963

Ah you might need to open a second browser window to receive it in the same room

I’m running it on my desktop browser and sending the avatar data from a Quest browser

by user 939271426349862963

I’m running it locally

by user 939271426349862963

the color of the avatar is being set up on the Quest browser and works fine there, but is not being replicated to the desktop browser. I can see myself moving the avatar (using quest controllers) on the desktop browser, but the color remains the same

by user 939271426349862963

And it’s not received?

Just tried this here real quick, sending /receiving works for this case. QuestBrowser is using the desktop localhost url i assume, right?

 async onEnable(){
        await delay(1000);
        this.context.connection.beginListen("test", (data) => {
            console.log(data);
        });
        const myData = {
            time: Date.now(),
        };
        console.log("SEND");
        this.context.connection.send("test", myData);
    }