URL rewrite and change first scene

Hello,

I’ve a PlayCanvas default loading screen (with a customized loading.js) and a world map with 3 destinations, let say A, B, C. When selecting a destination, I’ve a loading scene then the destination scene.

I’m figuring out the best way to let the customer accessing directly a scene via an URL. https://mywebsite.com gives access to the map, but I would like something like https://mywebsite.com/?destination=a and arriving directly on the destination.

Via JavaScript APIs, I can:

window.top.location.href // watch current/requested url
window.history.pushState // rewrite url
document.referrer // see from where user is coming

But as far as I know, I can’t prevent to load the map scene first since it’s my primary scene. Unless I deeply change the loading.js for moving out directly in the app.on('preload:start'? But since there are many assets with preloaded checked, this might lead to many bugs when coming back to the map. Is there any examples?

Hi @Aymeric,

That’s a good question. And you are right, for editor based projects, you can’t really change the first scene that loads.

If you are ok with hosting the build yourself, then you can easily add your scene selection logic to the __settings__.js file. That’s where the global var SCENE_PATH is being set, which you can override (that’s not a JSON file, it’s regular JS so you can add code):

image

That change will automatically be picked up by the __start__.js script, so no further changes are required.

1 Like

The way I would work around this is have an almost blank starting scene that only has a script to load the correct scene based on URL parameters and will fire a custom app event once the real scene is loaded.

The loading script will be modified so it only hides the splash on the custom app event.

Leonidas method is better as it avoids and extra load.

1 Like

Thank you @yaustar and @Leonidas for your quick responses!

It’s a bit sad that PC doesn’t offer a built-in scene swap url system / rewriting. But obviously, this really depends on the architecture & loading logic.

Having to rewrite the _settings__.js file each time and changing my app logic didn’t fit yet, so I did the ugly way:

var RewriteUrl = pc.createScript('rewriteUrl');

RewriteUrl.attributes.add('url', {type: 'string'});

RewriteUrl.prototype.initialize = function()
{
    const splits = window.top.location.href.split("?");
    const id = splits[1];

    if (!Utils.alreadyLaunched && id == undefined) // default is map
    {
        console.log("empty url, default site");
        Utils.alreadyLaunched = true;
        return;
    }

    if (id == this.url)
    {
        console.log("same url than default scene, return");
        Utils.alreadyLaunched = true;
        return;
    }

    // if the previous page is empty (direct link) or we come from an other website, force reload
    if (document.referrer == "" || window.top.location.hostname.indexOf(document.referrer) == -1)
    {
        //console.log(window.top.location.hostname, document.referrer, window.top.location.hostname.indexOf(document.referrer), window.top.location.hostname.indexOf(document.referrer) == -1);

        if (!Utils.alreadyLaunched)
        {
            console.log("force change scene: " + id);

            this.loadScene(id);
            Utils.alreadyLaunched = true;
        }
    }

    window.onpopstate = function(event)
    {
        const splits = document.location.href.split("?");
        const id = splits[1];

        if (id == undefined)
        {

        }
        else if (id == "map")
            this.loadMap();
        else
            this.loadScene(id);
    }.bind(this);
    
    window.history.pushState('', '', "?" + this.url);
};

Next time will have to consider this from the beginning!

1 Like