[SOLVED] app.loadSceneHierarchy seems to be broken

Hello fellas, Mikefinch is back in town.

I got a trouble with scenes. Once I tried to manage it in game and there are some issues, I guess.
My workflow was pretty like in that tutorial.

First of all, I removed my current stuff.

pc.app.scene.root.destroy()

And then I loaded new scene by it’s ID like that:

pc.pc.app.loadSceneHierarchy(587374)

Suddenly I got an error in console, it says that one of my scripts couldn’t find object on the new scene.
I initiated it by this way:

Magnet.prototype.initialize = function() {
    this.player = this.app.scene.root.findByName("player");    
};

So this.player was null. I thought PlayCanvas appends all entities to scene’s root and then inits scripts. When primary scene is loading it seems to be that. But not by loadSceneHierarchy

What is a proper way to load my scene with assets, connected with other entities?

ALSO I just forked tutorial project and it has problem with assets too. I’m not sure it is the same sh… trouble, but I guess it’s better to be fixed?

Thanks a lot.

And I have to point that error was thrown by child entity when it tried to find parent one.

image

When you fork that project, remember to update the scene ID attributes on the script attached to the camera. When you fork a scene, new scenes are created and the IDs change. But the attributes remain the same, because they’re ‘just text’.

Okay, that’s clear, my bad!

What about my main problem?..

I can’t tell unless I can run something and debug. Got a small repro for me?

Sure, https://playcanvas.com/project/498231

Second and third scenes. Third is primary and I try to switch for second.

What are the steps I need to take to trigger the exception?

var oldHierarchy = pc.app.root.findByName ('Root');
pc.app.loadSceneHierarchy("587372.json", function (err, parent) {
       oldHierarchy.destroy();
});

That doesn’t explain to me how I trigger the exception by running your project. :slight_smile:

I need something like:

  • Open scene ‘third’ in Editor.
  • Launch scene.
  • Press W key
  • See exception in JS console.

Okay, I just implemented this behavior.

Load project (scene third) and press Q to see exception in console.
Now It says that played doesn’t exist, but I think it’s the same problem.

   if (this.app.keyboard.wasPressed(pc.KEY_Q)) {
         var oldHierarchy = this.app.root.findByName('Root');
        this.app.loadSceneHierarchy("587372.json", function (err, parent) {
               oldHierarchy.destroy();
        });
    }

in scripts/Ship.js on 174 line

I really hope I got you right :frowning:

Looking at this as well. It looks like for some reason, the old hierarchy is not being destroyed during oldHierarchy.destroy(); but all the components have been destroyed. So in the new scene after the load, the magnet script is find the player entity that has no components from the previous scene.

Edit: Looking at this more, removeChild never actually executes this line: this._children.splice(i, 1); to remove the child from the parent.

What do you mean? Probably I have to destroy this.app.root instead of this.app.root.findByName("Root") ?

In any way, it doesn’t work. I think problem in handler.
Even if i comment appending new hierarchy to root, it gives me an error.

image

Dive down, pc.SceneParser inits script component on entities, while it is still in not hierarchy.

So I see that define “links” to another entity in Script.prototype.initialize is wrong way.
What is a proper way to do that?

And what does pc.ComponentSystem.initalize do? I am really confused with it.

In my opinion it should work this way:

  1. Get and parse new heirarchy
  2. Remove old hierarchy
  3. Add new
  4. Init scripts

But now it’s like:

  1. Get and parse
  2. init scripts
  3. Add new
  4. Remove old

I think there is a bug with entity.removeChild where the child is not actually being removed. I need to make a small repro case to be sure. (entity.destroy makes calls toentity.removeChild under the hood).

Yes, okay, but what do you think about initiating scripts before entities were added to root? Why it happens?

What makes you think that is what is happening?

Take a look at loadSceneHierarchy function - it loads scene from url, parses it by pc.SceneParser.

image

Afterwards, it appends new root entity to pc.app.root and then should init components, like scripts, etc.

But, even If I remove this invocation, handler (pc.HierarchyHandler) inits it when creates.

I mean this line:
var entity = handler.open(url, data);
Parses data, creates entities with components and inits them

So calling pc.ComponentSystem is unnecessary, since handler do the same. And it’s wrong, because my entities still are not appended to root.

So, in a nutshell, if you have no links to another entities into your prototype.initalize, it works fine, but if you do, you get an error about that, because it calls before entities were appended to scene.

This is the bit I’m confused about. What do you mean by this?

In the tests I’ve done with your project, your entities are added before initialize is called.

Edit: this is what the scene hierarchy looks like after the scene load:

==================
Magnet.js?id=11066478:31  Untitled
Magnet.js?id=11066478:31 - Root
Magnet.js?id=11066478:31 -- MainCamera
Magnet.js?id=11066478:34 Func {name: "MainCamera", tags: Tags, _labels: {…}, localPosition: Vec3, localRotation: Quat, …}
Magnet.js?id=11066478:31 -- player
Magnet.js?id=11066478:34 Func {name: "player", tags: Tags, _labels: {…}, localPosition: Vec3, localRotation: Quat, …}
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Camera
3Magnet.js?id=11066478:31 --- Magnet
Magnet.js?id=11066478:31 --- Sparks
Magnet.js?id=11066478:31 --- Point Light
Magnet.js?id=11066478:31 --- RootNode
Magnet.js?id=11066478:31 ---- lp
Magnet.js?id=11066478:31 -- Box
Magnet.js?id=11066478:31 --- Untitled
Magnet.js?id=11066478:31 -- Foobar
Magnet.js?id=11066478:31 - Root
Magnet.js?id=11066478:31 -- MainCamera
Magnet.js?id=11066478:34 Func {name: "MainCamera", tags: Tags, _labels: {…}, localPosition: Vec3, localRotation: Quat, …}
Magnet.js?id=11066478:31 -- player
Magnet.js?id=11066478:34 Func {name: "player", tags: Tags, _labels: {…}, localPosition: Vec3, localRotation: Quat, …}
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Engine
Magnet.js?id=11066478:31 ---- Engine light
Magnet.js?id=11066478:31 ---- Box
Magnet.js?id=11066478:31 ----- Untitled
Magnet.js?id=11066478:31 --- Camera
3Magnet.js?id=11066478:31 --- Magnet
Magnet.js?id=11066478:31 --- Sparks
Magnet.js?id=11066478:31 --- Point Light
Magnet.js?id=11066478:31 -- Box
Magnet.js?id=11066478:31 --- Untitled

How did you get that?

Oh, then, why can’t my Magnet component find it’s parent by
this.player = this.app.scene.root.findByName("player");

?

Reclusive call and print out through the hierarchy (See magnet.js) https://playcanvas.com/project/535191/overview/griper-drive-from-forums

The print out of the tree shows it still has entities from the third scene after the scene load but all the components have been removed so it will find the first player entity but it doesn’t have the rigidbody components etc.

this.app.scene.root.findByName("player");

Should also be:

this.app.root.findByName("player");

As far as I know, this.app.scene doesn’t have a root property.