Example using the decorator @syncfield()

Hi, I´ve already asked this but I lost the post.
Could you give an example of how to use the decorator @syncfield() if I want to achieve that all the players, who are in the same SyncedRoom , can modify one (and share) one data array (like a boolean, string or object array), with “modify” I refer to change the elements of the array and that change can be “see” for the other players.

Original Post on Discord

by user 632418299711324161

Hello there – we have an experimental AI bot :robot: that might be able to help you with your question. Would you like to try this out?

How it works:
Reply to the messages of the bot that end with a thread_id to interact with it and ask follow-up questions. You can also mention the bot directly in this channel to get help.

Help requested: please wait a moment…

Here is what I found for you :brain: Discord

Hello DiegoEloko,

To share an array across all players in the same SyncedRoom where they can modify the contents, and have those changes reflected to the other players, you can use the @syncfield() decorator. This decorator synchronizes the field’s value across the network for all players in the same SyncedRoom.

Here’s an example using a string array, but the same concept applies to boolean or object arrays:

import { Behaviour, syncfield } from '@needle-tools/engine';
import { SyncedRoom } from '@needle-tools/engine/components/networking/SyncedRoom';

export class SharedArrayComponent extends Behaviour {
    
    @syncfield()
    public sharedData: string[] = [];
    
    private syncedRoom: SyncedRoom;

    awake() {
        this.syncedRoom = this.getComponent(SyncedRoom);
    }

    start() {
        if (!this.syncedRoom) {
            console.error('SyncedRoom component not found on the GameObject.');
            return;
        }
        
        // Additional setup if needed.
    }
    
    modifyArray(index: number, newValue: string) {
        if (index < 0 || index >= this.sharedData.length) {
            console.error('Index out of bounds.');
            return;
        }
        
        // Modify the shared array.
        this.sharedData[index] = newValue;
        
        // Notify the SyncedRoom to synchronize the change.
        this.syncedRoom.notifyChange();
    }
}

thread_SZ6JFogl6sygOMxH50iSe2Kw

To add a new element, you would call .push() on the array and then call .notifyChange() on the SyncedRoom. To remove an element, you can use array functions like .splice() and then call .notifyChange(). Remember that every time you modify the shared array, you need to call .notifyChange() on the SyncedRoom component to update all clients in the room with the new array state.

Please ensure that the SyncedRoom component is properly set up in your project to use network synchronization as intended.

1 messages left GPT 4
thread_SZ6JFogl6sygOMxH50iSe2Kw
Thanks for your feedback!

The .notifyChnage method from SyncedRoom seems to no exits. Could you explain me what does it suppose to do and how can I implement it considering the example of SharedArrayComponent ?

by user 632418299711324161

I apologize for the confusion. In Needle Engine, the method to synchronize changes within a SyncedRoom is actually .markDirty() instead of .notifyChange(). This method marks the component as dirty, which then triggers the synchronization to all other clients in the room. Here’s how you could use it:

modifyArray(index: number, newValue: string) {
    if (index < 0 || index >= this.sharedData.length) {
        console.error('Index out of bounds.');
        return;
    }
    
    // Modify the shared array.
    this.sharedData[index] = newValue;
    
    // Mark the sharedData field as dirty, triggering synchronization.
    this.syncedRoom.markDirty(this, 'sharedData');
}

After modifying the shared array, you use .markDirty(this, 'sharedData') to inform the SyncedRoom to update the array for all clients in the room.

This will ensure that changes to the shared array are propagated to all players in the SyncedRoom.

0 messages left GPT 3.5
thread_SZ6JFogl6sygOMxH50iSe2Kw
Thanks for your feedback!

That method neither exists :frowning_with_open_mouth:

by user 632418299711324161

You have reached your limit of 2 messages… please try again in a few hours

Hi @DiegoEloko the docs have a very simple example

You can also find another example here in the networking docs Networking | Needle Engine Documentation

About this example, if any player could call the onNumberChanged (if that method where public) , the field myNumber would change for all the players ?

by user 632418299711324161

yes for all in the same room

Okey okey , thanks

by user 632418299711324161

Hi :slightly_smiling_face: Hoping you doing well, I ask for help with a networking question.
I have a class which has a @syncField (an array) and I want that the players in the same room can modify this array. I have tried the example of the documentation but nothing happened.
This is my testing class which is attached to a NetworkingTesting gameObject:

import { Behaviour, syncField} from "@needle-tools/engine";

export class ShareElementsManager extends Behaviour{

    
    @syncField(ShareElementsManager.prototype.reasingNetworkValue)
    private shareArray :string[] = []; 
    
    start(): void {
    }

    update(): void {
        if(this.context.input.getKeyDown() == 'x'){ 
            this.addNewSharedElement("1"); 
        }
        if(this.context.input.getKeyDown() == 'y'){
            this.showSharedElement();
            
            
        }

    }

    public addNewSharedElement(newValue:string){
        this.shareArray.push(newValue);
        //this.syncedRoom.markDirty(this,'shareArray'); 

    }
    
    public showSharedElement(){
        console.log(this.shareArray);
        
    }

    reasingNetworkValue():void{
        this.shareArray = this.shareArray; 
    }

}

I want to trigger addNewSharedElement method from outside that class and change the array for all the players but when I logg it , it seems that it can only be changed locally. How can I share the array with all the players ? Srry if I continue asking about this decorator :sweat_smile:

by user 632418299711324161

You need to reassign the array so the syncField decorator gets that it has changed. Like you do in the reassignNetworkValue function

Pushing a new value is not enough if its an array or an object because the syncfield doesnt watch all entries or fields in an object or array (it would be too complicated and computationally intensive if reassigning the field is enough - and more explicit)

ReassignNetworkValue shouldnt be called from the onchange event btw - the argumemt in the syncField(…) Is a method that is called after it has changed!!!

So it’s already reassigned :slightly_smiling_face: no need to do it again there

Here is another example that is similar to your case: needle-engine-samples/package/Runtime/_Shared/SampleScripts~/SimpleLeaderboard.ts at 93efed84e2d8c7070118df05d1ee47ca50efeba7 · needle-tools/needle-engine-samples · GitHub