How do you get objects from another scene through python?

I have this script to get an object I need from the current scene:

scene = bge.logic.getCurrentScene()
obj = scene.objects["scene1_object"]

I have another scene for the game hud as an overlay scene.
How can I write it to get the objects from the other scene?

Hi Saranoske,
You can access/get another scene with the function bge.logic.getSceneList()
The 1 requirement of that function is that the scene must be already active, otherwise Blender throws a ‘scene does not exist’ warning error.

Here’s an example.

  1. You have your game_scene.
  2. You have your ‘hud_scene’.

Lets assume you’ve already added your hud_scene with either the Scene Actuator or with the code function -

bge.logic.addScene("hud_scene", 1)

Then to access the objects of the other scene (In this case we mean the hud_scene since I assume the logic is being done from the game_scene)
To do that we use the following code.

bge.logic.getSceneList()["hud_scene"].objects
2 Likes

Thank you, this works but only if I write it like this:

bge.logic.getSceneList()[1]

Otherwise, it gives me this error:

TypeError: list indices must be integers or slices, not str

Is there any way how can I tell which number corresponds to a specific scene?

each scene has a scene.name you can compare.

for scene in bge.logic.getSceneList():
    if scene.name == "hud_scene":
        #do things

but its safe to assume the scenes are ordered by time added. 0 being main, 1 first overlay etc

1 Like

@Saranoske
This is a known ‘bug’ in BGE.
UPBGE versiosn have the bug fixed as you can see for yourself below.

If you’d rather stay with your BGE version, @Daedalus_MDW’s method gets the job done.

1 Like

I see, thank you. It still works with numbers, co it’s no big deal.

1 Like

Ok, I understand how this works now.
If the main scene is 0 and the other scenes added have numbers in order that they’ve been added, than that’s not a problem.

Here this is what i use

def get_scene(scene_name):
    
    scenes = logic.getSceneList()      
    scene = None
         
    for sce in scenes:
        if sce.name == scene_name:
            scene = sce
    
    if scene == None:     
        print('\n*** No scene found with the name: ' + str(scene_name) + ' ***\n')
    else:
        return scene


def get_object(scene_name, object_name):
      
    scene   = get_scene(scene_name)
    object  = scene.objects[object_name]
    
    return object


#any scene
scene = get_scene('scene_name')

#any object from any scene
obj = get_object('scene_name', 'object_name')
#keep in mind, scene must be active else you can't acces them (so a over/underlay scene)
2 Likes

Thank you, this looks really useful.

2 Likes

there is a few optimizations you can make in the get_scene function, it can basically be cooked down to this.

def get_scene(scene_name):
    
    scenes = logic.getSceneList()      
   
    for scene in scenes:
        if scene.name == scene_name:
            return scene # break early, no need to continue when scene is found.
     
    print('\n*** No scene found with the name: ' + str(scene_name) + ' ***\n')
    return None
2 Likes

This actually depends on how you script the other scripts and do the checks for they values returned…
I rather have 1 message saying scene is not here, then having it spam console.

This does not check if it got a scene, or has None, so it will try to get a scene every tic. But i would still keep the if/else just to not have to code checks everywhere and just have a single point where i spit out an error (console always tells the line causing the error + the error itself).

i have tested the code and it works as intended, if it finds a scene it returns the scene, if not then it returns None, exactly the same as your code does.

No not really,

When scene == None, script ends and does not return anything so all comes to a stop. Yours wil return None everytime and thus you need to check in your ‘other’ script if the value is set or not, else you get even more errors.

That is what i mean.

nope, there is a return statement inside the loop that returns the scene when found, never gets to the print statement if the scene exits.

Sorry bad wording i guess, i did not mean that your script return None everytime, it only does this when it fail to grab a scene with the name. And that is where i’m after, when it fails, you need to have a check to check if the value is set in your other/extended script.

So only when fail to get scene.

This one will fail, because it does not have a check if value is set. That’s why i have the check to return scene or only print the error.

your script also return None, it is the default behavior in python when no return statement is hit at the end.

def do_nothing():
    pass

result = do_nothing()
print(result)

this code snippet prints None if run.

Oh wow, now i feel stupid! you’re right.

1 Like

it is okay, you where just defending your code. :wink:

1 Like

No it’s not that, i really was convinced that it would stop, because we aren’t returning anything, so haha yeah i’m feeling pretty stupid now.

now that you have realized this, then you should take a closer look at your get_object function.

hint:

object  = scene.objects[object_name]

would fail if scene is None