Is this a bug?

I’m using Blender 2.71.

Here’s the example Blend file:
remote_access.blend (429 KB)

Today I was working on a UI interface, things like healthbars, message logs etc… on a separate overlay scene. It makes sense to call a reference to this scene from the main scene (where all the info is, such as players, positions, health enemies etc…) and make changes using a controller in the main scene. This works fine for things which are on the active layer of the overlay scene, but when I try to add an object from the hidden layers of the overlay scene using ui_scene.addObject() I get errors.

The first type of error is that I can’t call hidden objects by name from the inactive layer:


It says the object doesn’t exist in the scene, but it does! As can easily be proved by printing the inactive objects from that scene:


So, I tried using the objectsInactive list to add objects:

adding_object = ui_scene.objectsInactive['cube']

This works, but results in some strange behavior. When adding a text object from the inactive scene it either crashes Blender, a straight crash to desktop with no explanation, or it adds the text with a weird orientation.

Usually when you use addObject it aligns the added object to the position and orientation of the reference object, in this case, a special object I’ve added to the overlay scene for this purpose. But in this case, the text seems to be aligned to the world position of the main scene, (see the image above, the camera in the overlay is looking straight down, the text should be flat, but is aligned to the floor of the main scene).

I’ve found a work around for now, but really there should be no problem using python to add an object in one active scene using a controller in another active scene. Or if there is, there should be something in the documentation saying why.

Looks like a bug.

The transform of the text object follows the circle, but it seems to be displayed through the view matrix of the main scene.

It seems like a bug to me.

But here’s a question, why are you trying to add objects in the overlay scene? If the overlay is just supposed to be a UI, why not have objects you don’t need be off-view of the camera, and swap their positions when you want to bring them in?

Yes, that’s a valid option. As I said, I’ve got a work around, but I do like using add object to place things like radar blips or message log text or using it as a redraw system, where I have a loop to delete all drawn elements each pass and then redraw them by adding them again. It’s easier than keeping track of added objects and not much different in speed. It’s also great for things where the number of elements can change greatly from second to second, like a radar, where you could have dozens of enemies one minute and none the next, or path visualization, where the length of the path can change every single frame.

Right now I’ve got a controller object in the overlay scene which is doing the calculations from data collected from the mains scene and then adding objects. It’s a work around, but I’d prefer to keep all the logic in one scene, easier to deal with in the long run.

I’ve explained this before, but I’ll explain it again here.

Whenever you call addObject() with a string as the first argument, Blender searches for the object in the scene the calling controler resides in, NOT in the scene you’re calling addObject() on. Since the calling controller reside in the main_scene, it searches for “text_object” there instead of the “ui_scene”. While this behavior is likely a bug, the workaround if very simple. Just replace your addObject() call with this:

textObj = ui_scene.objectsInactive['text_object']       
ui_scene.addObject(textObj, reference_object, 0)

Does this mean you can get an object from one scene and add it to another?

No, you can’t share objects across scenes during runtime. You can link an object to another scene before you start the game though. Currently the only way to get a single object into multiple scenes after you’ve started the game would be to use LibLoad to load it multiple times from an external file into each scene you want to use it in.

It makes me wonder, how many BGE users know that Blender allows them to link objects between scenes regardless of the layer they are in? I’ve used it a lot to link the player and camera setup across all of the different levels (the player usually won’t notice you start at the same coordinates every time as this method requires).

It’s a lot easier to use than libNew()/libLoad() and saves a lot of time when it comes to changing the logic of the player, you can even have the whole game in one .blend file and keep it manageable because of it.

@Ace Dragon
Yup, linking between scenes is great, but sometimes libload is good as well. Depends on the scale of the project. If you have more than 5-6 levels, you should probably libload it in and split the levels to external blends to avoid long start-up times/ram usage.

Seems like a bug from here as well. At the very least, it shouldn’t crash blender! So submit a bug report even if you find a workaround.

I’d question your program-structure. Why does the radar need to be run from the main scene? Surely it would be easier to have it run from the HUD and just reference the location of the player?

Well, there’s lots of times I’d want a script in one scene to be able to add an object in another, such as an inventory which is run from an overlay scene. In that case I drop an item and I want the player in the main scene to create that item and drop it on to the ground. it’s just a waste of processing to send a message to the main scene, and then have the main scene object carry out a function that could have been handled directly.

In other cases it’s just a matter of convenience, not to have to go back and forth from main scene to HUD and back again using messages or setting properties, we have the tools to work in one scene and do things in another one without having to send messages between them. But one of those tools is a bit broken, which makes me worry about other undocumented bugs that might crop up if I continue using this method.