Cannot Manipulate overlay scene objects

Hello, I have a HUD (overlay scene called FPS_HUD) on my FPS game, and am trying to edit game text on my FPS_HUD from the PLAY scene.

I am having trouble connecting to the FPS_HUD scene from the play scene:

I have on my camera an Always -> Python (HUD.py) -> scene (Add overlay scene FPS_HUD)

My code:


from bge import logic as GameLogiccont = GameLogic.getCurrentController()


HUD = cont.actuators["HUD_Sc"] #Getting the overlay scene actuator
cont.activate(HUD) #activating it
#HUD IS RUNNING NOW, shows up in scene


GameScene = GameLogic.getCurrentScene() #getting our Gameplay scene
HUDScene = HUD.scene #getting our HUD scene name (DOESN"T WORK)


scenes = GameLogic.getSceneList()
for i in scenes:
    print(i) #ONLY prints the Play scene, not my FPS_HUD scene!


#Ammo.Clip.Text = HUDScene.objects["Ammo.Clip.Text"] #ERROR.. apparently just stored as string...
#Ammo.Clip.Text = FPS_HUD.objects["Ammo.Clip.Text"] #Error, FPS_HUD not defined
bodybox = GameScene.objects["Body.Box"] #This one works though

It takes a frame for the added scene to actually be added into the game. Add a little delay after executing the actuator, or check the scene list to make sure the scene’s been added before continuing.

Wow that was embarrassingly easy… is there an easy way to add a delay? The only one I know is time.sleep, which doesn’t look pretty.

That is some convulsed python. Google PEP008 and find out some better ways to format it.
In short, you’ve tried to fit too much on each line, leading to syntax errors and low readibility.

(Please, don’t import logic as GameLogic. It is the same length as bge.logic so there is no reason to)

I would just use an always to add the HUD scene, it’s much easier.
You add it correctly, but you never get the scene. You get the scene name.

HUDScene = HUD.scene

Should be replaced with:

HUDScene = [sce for sce in bge.logic.getSceneList() if sce.name == 'HUDSCENENAME'][0]

The reason that this:

scenes = GameLogic.getSceneList()
for i in scenes:
    print(i)

only prints Play, is because the HUD scene hasn’t been added yet. It adds on the next frame.

As for your next couple of lines, they are so of and not pythony at all.

So let’s get the Ammo clip object object:

ammoClipObject = [ob for ob in HUDScene.objects if ob.name = 'AMMOCLIPOBJECTNAME'][0]
#Now we can set the text
ammoClipObject.text = 'Whatever the text should be'

“That is some convulsed python” -> Some of that I realize looks bad… I was trying multiple ways to get the scene list and grab my specific scene, so it was sloppily coded. Also, never coded python before this :smiley:

The tutorials and examples I’ve found usually had it listed as GameLogic, so I started using that and never stopped. It helped a little when I started and just haven’t switched off it yet, although I plan to.

I did originally have the always adding the HUD scene, but for troubleshooting I always reduce it to simplist form and start from there.

On a side note, should I not name my objects with dots? Blender seems to do this alot, but I’m quickly realizing that python does it too… might make it difficult :smiley:

My last line… why is my line bad if I change it to this?

AmmoclipOBJ = HUDScene.objects["Ammo.Clip.Text"]
AmmoclipOBJ.Text = "text"

How is this better… I know the name of the object, so this seems like more work… am I missing something?

ammoClipObject = [ob for ob in HUDScene.objects if ob.name = 'AMMOCLIPOBJECTNAME'][0]

Good advice for sure, but isn’t this:

the same as this:


ammoClipObject = HUDScene.objects['AMMOCLIPOBJECTNAME']

Thought so, thanks, his other advice is good though…

Also, any way to easily delay a script for x number of logic tics?

Okay, it isn’t pretty, but this is what appears to work without throwing errors…


from bge import logic
cont = logic.getCurrentController()
own = cont.owner


try:
    HUDScene    
except NameError:
    if own["init_HUD"] == 1:
        HUDScene = [sce for sce in logic.getSceneList() if sce.name == 'FPS_HUD'][0]
        AmmoClip_TextOBJ = HUDScene.objects["Ammo.Clip.Text"]
        AmmoClip_TextOBJ.text = "0"
        AmmoClip_TextOBJ.color = [0,73,100,45]
    else:
        own["init_HUD"] = 1

Sorry about that, I was doing the search for properties code when I realised he was wanting an object name…

That new code looks good except that ‘HUDScene’ will always throw an error, as you never define it.
Instead it should be:


try:
    HUDScene = [sce for sce in logic.getSceneList() if sce.name == 'FPS_HUD'][0]
except KeyError:
    '''All the other stuff'''''

And yeah, naming objects with dot’s isn’t a good idea. It’s what had me confused, that you had “AmmoCount.text” as an object. I thought you were trying to access the text section of the object ‘AmmoCount’

I normally use Camel Case:
ammoBox
ammoCounter
ammoDisplay
ammo
thisIsAnotherExample

I use this for naming variables within python and game properties.

For game objects I prefix it with the first character of the scene name, and then use normal english:

MMouseCursor (Mouse Cursor object in the Menu scene)
GAmmoBox (Ammo box objects in the Game scene)

This makes sense when you look at the outliner.

I suggest to simply write a function.
This is better to read and more efficient:


import bge

def testSceneFinder(cont):
    scene = getSceneByName("Scene")

    if scene:
      print("found scene with name", scene.name)
    else:
      print("no scene with the given name found")

def getSceneByName(sceneName):
  for scene in bge.logic.getSceneList():
    if scene.name == sceneName:
      return scene

BTW: it does not matter if you import GameLogic or bge.logic. bge.logic is “just” another alias for GameLogic.