[SOLVED] Script loading unexpectedly on new scene

Considering the real-time multiplayer tutorial, I tried to add a new scene which doesn’t reference the network.js script.

However, when I load the scene from a UI button click, I get an error from the network.js script although it’s in the root/previous scene and not the new one.

I’ve been having trouble loading additional scenes with the example provided, my workaround logic consists of separate server instances (Glitch) per scene. I even attempted duplicating the network.js script per scene to see if it would stop signaling errors. None of which worked.

Here’s an 1 example error I’m receiving upon arrival on new scene:

[network.js?id=47856432&branchId=de38b90e-ba56-4006-b311-45eabcac661f:89]: Uncaught TypeError: Cannot read property 'teleport' of undefined

TypeError: Cannot read property 'teleport' of undefined

I’m aware of asset Preload for network.js but this stops execution when on root scene.

Any ideas?

Sounds like you haven’t unregistered to a global event in the script when it is destroyed

1 Like

Hmm, that may be the case but what would be an example of a global event?

The event listeners for the player? I don’t understand, the provided code setup has barely been tweaked at this point… the Network.prototype.update() function maybe?

It’s also weird that you must delete the old hierarchy before loading a new scene, which causes issues for multiplayer in itself. For instance if one player travels to a scene, the scene hierarchy is deleted for all connected clients.

Anything this is listening to an event that is not on the same entity or script. eg.

this.app.mouse.on('mousedown', callback, this);

This would be a ‘global’ event as the app and mouse object lifetime is not controlled by the entity or script.

You don’t have to. You can load multiple scenes at once. One client state should not control the state of other client states. The state of the world should be controlled by the server. Whether a client loads/unloads scenes is irrelevant to other clients.

1 Like

Thanks as this response cleared a few things…

Idk this.app.root becomes confusing when considering new scenes, also I’m aware of loading multiple scenes but they just stack on top of each other which is why they need to be deleted.

How would I improve the network.js so it doesn’t error out?

As you’ve said, the scene stuff is not explained at all and because of that, it is assumed it is the same as Unity (which it isn’t)

We have a bunch of tickets lined up to vastly improve the documentation (scene loading is here) but it’s getting buried under support, feature requests and new features which I’m desperately trying to dig through.

Looking at network.js, it naively assumes that it’s on an entity that is not getting destroyed and it’s always active.

At a guess, I would say that on the script being destroyed, it should close the socket and null the global variables.

eg:

// initialize code called once per entity
Network.prototype.initialize = function() {
    this.player = this.app.root.findByName('Player');
    this.other = this.app.root.findByName('Other');

    var socket = io.connect('https://sore-bloom-beech.glitch.me'); // Glitch hosted server
    Network.socket = socket;
    
    socket.emit ('initialize');
    
    var self = this;
    socket.on ('playerData', function (data) {
        self.initializePlayers (data);
    });

    socket.on ('playerJoined', function (data) {
        self.addPlayer(data);
    });

    socket.on ('playerMoved', function (data) {
        self.movePlayer(data);
    });

    socket.on ('killPlayer', function (data) {
        self.removePlayer(data);
    });

    this.on('destroy', function () {
        socket.close();
        Network.id = null;
        Network.socket = null;
    });
};

I’m not too clued up on socket.io but I would think that it stop it from receiving new events.

1 Like

This indeed helped, I should still be able to receive new events though. I just needed this to stop being called as I’m separating server instances per scene for better network performance.

In this case, players can create “rooms” in each scene and host them for other clients to join.

Considering the state of PlayCanvas, it’ll only get better by tackling issues/requests at a time. It’s still a great product without the newer concepts yet implemented :+1:

In which case, the server and client would need to be updated to have rooms created. For example the server can partition the users so that events sent to a room/party are only broadcasted to others in that room/party rather than the whole server which is what it is currently and beyond the scope of the tutorial.

The network script and other managers should then probably be in a scene that doesn’t get unloaded (eg a master scene as shown here: Game wIde Global variables best practice)

Thank you, that’s appreciated. Documentation is a major thing for us and been slowly getting all the issues and areas we want to tackle: https://github.com/playcanvas/developer.playcanvas.com/milestones

It’s just trying to get to it without more ‘urgent’ stuff cropping up.

1 Like

Yes I’ve managed to implement the rooms however it only works on the main scene.

The problem is getting it to work for additional scenes, maybe having a global player and netPlayer entity will solve it. I will continue to tackle this considering what you gave me.

I’m aware that the scope of this exceeds the tutorial, just wanted some guidance considering the engine.

@yaustar Upon further inspection of the Global thread you sent, is AppManager built into PlayCanvas? So ultimately I’d make a entity named AppManager and place the player entities as childs of this??

No, it isn’t. It’s an entity that the developer made. It’s done in a similar way to this example: https://developer.playcanvas.com/en/tutorials/additive-loading-scenes/

1 Like

Is there an event for initialization? For instance this happens when destroyed, but is there an event to call on initialization other than the standard initialize function of a script?

Are you thinking more of a ‘reset’? The engine doesn’t have a ‘reset’ or re-initialisation concept.

However, you can fire your own events on the script type/component/entity.

e.g

Network.prototype.initialize = function() {
    // other code

    this.on('destroy', function () {
        socket.close();
        Network.id = null;
        Network.socket = null;
    });

    this.entity.on('reset', function () {
        // some code
    }, this);
};

/// Else where where you want to reset the player for whatever reason

thatPlayerEntity.fire('reset');
1 Like

Fairly interesting, seems like what I’m looking for!

Thanks for this, I did aim to reset the network values to original values.