Jump to content

Phaser 3 Scene / Phaser 2 State - passing data to init when start


pixelhijack
 Share

Recommended Posts

Does anyone know how to pass data into the game scene in Phaser 3 as you could do in Phaser 2 when started a state? 

game.state.start('Game', true, true, { data: 'this is some initial config' });

Phaser 3 Scene was Phaser 2 State, which you could provide parameters, the 2-3rd was as i remember caching, the 4th could be and data, which became available in the State's init() {} method as init({data}). 

In Phaser 3 a Scene has a second, data param, but it is not clear how it is used, the init method is not getting it, and the documentation is not ready for that as far as i know. 

Link to comment
Share on other sites

@samme @PixelPicoSean It is not working for me: i got an empty object as passed in data to my Scenes if i follow the documentation (https://phaser.io/phaser3/api/scene-manager), even with Phaser 3.1.2 and 3.2.0 too: 


const bootScene = {
    key: 'boot',
    active: true,
    init: (config) => {
        console.log('[BOOT] init', config);
    },
    preload: () => {
        console.log('[BOOT] preload');
    },
    create: (config) => {
        console.log('[BOOT] create', config);
    },
    update: () => {
        console.log('[BOOT] update');
    }
};

const gameScene = {
    key: 'game',
    active: true,
    renderToTexture: true,
    x: 64,
    y: 64,
    width: 320,
    height: 200,
    init: (config) => {
        console.log('[GAME] init', config);
    },
    preload: () => {
        console.log('[GAME] preload');
    },
    create: (config) => {
        console.log('[GAME] create', config);
    },
    update: () => {
        console.log('[GAME] update');
    }
};

const gameConfig = {
    type: Phaser.CANVAS,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: [ bootScene, gameScene ]
};

const game = new Phaser.Game(gameConfig);
game.scene.start('boot', { someData: '...arbitrary data' });

By stepping into the game.scene.start() method call in Phaser 3, as i see what is happening here is first the scenes are getting a "default" key, which only later gets overriden with the given key (here "boot" and "game"), but the default data remain the fallback empty object: 

start: function (key, data)
    {
        if (data === undefined) { data = {}; }

        //  if not booted, then put scene into a holding pattern
        if (!this.game.isBooted)
        {
            for (var i = 0; i < this._pending.length; i++)
            {
                var entry = this._pending[i];

                if (entry.key === key)
                {
                    entry.autoStart = true;
                    entry.data = data;
                }
            }

            return this;
        }

        var scene = this.getScene(key);

Can this be a bug...? 

Link to comment
Share on other sites

9 hours ago, PixelPicoSean said:

You set both boot and game scene as active which means they are automatically started by the game, and Phaser 3 won't start a scene if it is already started and active. So your data will never get passed to those scenes.

Still, if i set either one active: false, or both, or delete the active property at all, i got the very same result, my data not passed in, i got the default empty object only. 

In Phaser 3.2.0. SceneManager.js:947 while debugging i see this, with the previous settings detailed previously, (which is from the docs) the entry.key is "default" while the key is "boot" which evaluates to false, so the entry.data will never set to what i'm trying to pass. 

for (var i = 0; i < this._pending.length; i++)
            {
                var entry = this._pending[i];

                if (entry.key === key)
                {
                    entry.autoStart = true;
                    entry.data = data;
                }
            }

@rich what is the expected behaviour here? Can this be also related to https://github.com/photonstorm/phaser/issues/3185 ? 

thanks for the help guys! Phaser rulez!!

Link to comment
Share on other sites

36 minutes ago, PixelPicoSean said:

Even you set the active of first scene passed to `config.scene`, it still gets activated since it is the first one(your bootScene). What is your purpose of passing data to the boot scene? You can simply start the second one from the boot scene with whatever data and it will just work.

In Phaser 2 I always used this for dependency injection, i passed all the level configs (big JSON containing asset paths, animation frames, creature props, etc, a declarative approach) to the level which was handled by State. Now i want to have the same architecture with Scene. 

Link to comment
Share on other sites

Maybe my understanding on Phaser 3 Scenes are not right, but i dont really think this should be the expected behaviour based on Phaser 2.x States. 

What I would expect, how it worked in Phaser 2 States, that i created a State for every phase of my game: Boot loading, Menu for selecting game modes for example, Game state for the actual game which could mean switching between levels etc, and I could pass any data to any State. 

Now in Phaser 3 as I see following the docs, and as you describe @PixelPicoSean seems like I cannot pass data, just to the second Scene? And also when starting one Scene from a first (the "Game" from "Boot") .create() it seems like both their update() methods are being called by turns - this was also not the case with Phaser 2.x States. 

Can someone approve that this is an expected behaviour (and correct my misunderstanding or point to documentation where it is described) OR if it is a bug? 

Screen Shot 2018-03-09 at 13.25.40.png

Link to comment
Share on other sites

12 minutes ago, PixelPicoSean said:

As I told before, all the scenes passed to the game config that set active will run automatically when the game start. Phaser3 allows scenes to run parallels, so it is actually expected behavior.

If i dont set it active: true, or explicitly set active: false, even both Scene, i get the very same result. 

Can you share a working config with my previously provided snippets where: 

  1. Scenes are initialized by their keys, and not "default"
  2. Not all scenes initialized active
  3. Data is passed to any Scene, even the first?

...because this was possible in Phaser 2.x, where States were consecutive phases of a game, able to pass data. If Phaser 3 is giving the possibility to run parallelly as a plus, it is cool, but if it is not backward compatible, that is not really. Do you think i can achieve these with Phaser 3 too? 

Link to comment
Share on other sites

I believe that when you pass multiple scenes in the game config object, all of them are added and the first one is started automatically. It's a little ambiguous.

So there's no need to start the Boot scene again, and that may be causing some of the trouble.

If you want it to work exactly like Phaser 2, I guess you should omit the scene config altogether and instead call scene.add, scene.add, scene.start afterwards.

Link to comment
Share on other sites

I am facing the same issue. I cannot make data get passed onto a scene... My use case is:

  1. Start LevelScene
  2. Stop LevelScene (I print isActive() here, it's false)
  3. Start LevelScene again with data
  4. Data never come up on LevelScene's create

In my case, I am trying to make a game with a level stucture similar to Angry Birds. Each level is mostly a different configuration of the same template. I obviously don't want to create 100 different level scenes. Can you suggest a reccomended way of dynamically passing config to a scene?

@samme, in your comment, I think you made a typo, what is the sequence you reccomended? Just scene.add and then scene.start?

Link to comment
Share on other sites

Ok, I digged around in the source code and I think I found what the "issue" is. Data are passed to scenes, only if the scene you are switching from is not running. I assume this is by design. Maybe that's what you meant @PixelPicoSean but I did not get it. Many of the examples I've seen, as well as the code I posted above, start a new scene from the create function. And that works fine when you have no data to pass. At that point, the currently runnig scene (eg BootScene) has not yet been fully initialised and is not considered as runnning.

I was looking for another hook to put my scene switch, but I could not see anything in the code, like created, or loaded, that is triggered after create has actually finished. So, for now, I put it in update, which is not great. The first time BootScene hits update, it will switch to the new scene with data passed to it.

Edit: Sorry, I might have "hijacked" (;))  this post @pixelhijack, I realised I am talking about a different issue than yours, as you are not switching from a scene to another.

Link to comment
Share on other sites

Thanks a lot for looking at this guys! @PixelPicoSean that did seem like bug to me as well, but the souce code made me think it could be like that by design. And if so, it probably would be nice to have a post-creation hook added to the lifecycle of a scene, for cases like mine. As it is a one time thing, that gets triggered after a scene is created. And I assume it might be quite common, as people create boot scenes that do nothing but loading assets. But in its absence, I agree, update is fine.

I guess I will raise an issue at the phaser repo then, and see what happens.

Link to comment
Share on other sites

@Stathis I already raised an issue for that, feel free to add anything new there, i'm looking into the SceneManager too to figure it out. https://github.com/photonstorm/phaser/issues/3363

Would be nice to have a clear view what is the flow in Phaser 3, Phaser 2 was kinda straightforward for me. To follow some architecture pattern for a game these intents would be good to know well. :D 

Link to comment
Share on other sites

2 hours ago, pixelhijack said:

@pixelhijack although it's possible there's still a bug involved, you still need to follow http://labs.phaser.io/edit.html?src=src\scenes\scene add manual start.js if you want to call scene.start outside of a scene or post-boot callback. That means you need to omit the scene key from the game config altogether and instead add the scenes manually as well.

Link to comment
Share on other sites

Ok i made codepens to illustrate these and why i think there is a bug or bugs, check the console for each pen: 

1. Previously: Phaser 2.6.2 Starting States with data: 

 

Expected behaviour: 

  • Start Boot State with initial data
  • Initial data is passed to State init (used as dependency injection for level / game JSON)
  • Start Game State with some other set of data
  • State methods are in order: Boot:init, Boot:preload, Boot.create, Boot:update, Game:init, Game:preload, Game:create, Game:update
  • Only active State is the last one started: Game

Phaser 3.2.0 Starting Scenes with data - manually

Expected behaviour: 

  • the same as in Phaser 2.x

Actual behaviour:

  • Boot is initialized with the default empty object, i cannot pass in initial data
  • Game scene is not started if i start it manually from Boot:create

Phaser 3.2.0 Starting Scenes with data - from config

 

Expected behaviour:

  • if you set active:false, or set delete key, it will be good

Actual behaviour:

  • Boot scene is only getting the default data object, cannot be passed init object
  • However, you can pass data to Game scene (why just here?)
  • does not matter if you set active:false, or remove it, or you do not set the key @samme
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...