Multiple Objects With Same Name

Hi, I am a bit stuck at the moment. The problem I am having is when I refer to multiple instances of the same object (Cube mesh etc). As they all have the same name only one object ‘responds’ to my python commands.

 
import bge
cont = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
source = scene.objects
keyboard = bge.logic.keyboard
wKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.WKEY]

class spawney():
    def __init__(self,emptyName):
        self.empty = source.get(emptyName)
        self.retrievecube = source.get('Cube')
        if self.empty['activated'] == False:
            self.addcube = scene.addObject('Cube',emptyName,0)
            self.empty['activated'] = True
    def move(self):
        if wKey:
            self.retrievecube.applyMovement((0,0.1,0),True)

jimmothy = spawney('EmptyTwo')
bruce = spawney('Empty') 
jimmothy.move()
bruce.move() 

The problem is that both cube’s spawn but only one cube moves when I press the w key. Could anyone help shed some light on what I need to make this work? I want both cubes to move when I press the w key.

EDIT

The solution was simple really in the end once I got my head around a few concepts. Thanks for the help everyone.

Ran this in a python controller in modular mode, which was new to me ( spawn_characters() and move_characters() (Always pulse on) ).


import bge
cont = bge.logic.getCurrentController()
own = cont.owner
scene = bge.logic.getCurrentScene()

class spawney(self,spawnLocation):
    def __init__(self,spawnLocation):
        own['spawn'] = scene.addObject("Player",spawnLocation)
        self.player= own['spawn']
    def move(self):
        wKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.WKEY]
        if wKey:
            self.player.applyMovement((0,0.1,0),True)

def spawn_characters():
    jimmothy = spawney('EmptyTwo')
    bruce = spawney('Empty')

def move_characters():
    jimmothy.move()
    bruce.move()


Some remarks:

Use module mode, don’t run this in script mode.
Store a reference to the original cube, or its python ID (in this case, scene.objects has a from_id function that you can use to get the GameObject by its python ID)

Thanks agoose for your patience and swift reply. When you mention a reference, do you mean something like a dictionary?

Is anyone aware of any tutorials explaining module mode and how to implement it? (I’m aware of the button, but how do I refer back to created classes and functions in modules in my scripts)

It seems that you’re trying to perform some kind of object management system. You shouldn’t use classes if all they will do is wrap things like that - in this case it will be easier for you to just use functions. However, I think that you might want some more flexibility, so here is an example system.

untitled.blend (509 KB)

Thanks very much agoose!

You are correct in saying I want more flexibility, and that I’m trying to perform some kind of object management system. Often I struggle to realise what I am even trying to do! That code is extracted from part of a character management system, which controls character movement, their inventory and actions as well as spawning them and turning them into rag dolls (spawning rag dolls in their place).

Looking at the blend their are a few things I still need to learn, but you have solved my problem and I’m looking forward to learning more by studying the blend.

Ok, so this was not as easy as I originally thought it was going to be.

I still cannot manipulate objects with the same name. I have edited the untitled.blend file to closer match my setup. I am trying to move the objects independantly. How can I do this?

Store a reference to the original cube, or its python ID (in this case, scene.objects has a from_id function that you can use to get the GameObject by its python ID)

How do I get the reference or python ID and ask the specific object to move? (1 of the spawned ‘Cube.001’).

test 2.blend (506 KB)

You have to understand that game objects are objects and not names. Your problem is that you use an insufficient object search:


scene.objects.get('Cube')

Why is it insufficient? Because it returns either None, or any of the objects with the name “Cube”. It does not give you the other objects with the same name nor does it tell you there are more.

A more sufficient search is:


import bge 
...
def findByName(name):
   return [gameObject for gameObject in bge.logic.getCurrentScene()
          if gameObject.name = name]

Obviously it searches the current scene only. But you can change it to search all scenes.

Hi Monster, thanks for your reply.

I am having a hard time understanding this. Are you reffering to my original post? I am aware that objects are objects and not names, but I am unaware of how to make objects move without reffering to there name… I think…

What I think I need to do (which I don’t think I have made very clear).

  1. Spawn an Object (‘Cube’)
  2. Spawn the same item
  3. Manipulate each (‘Cube’) seperately

Can I cheekily request you embed that code into my original example so I have a full working demo I can learn from?

Could you can suggest some reading, or some posts to read? I am still very new to python.

Any help is greatly appreciated!

1 Like

Hi boggle!

Solution: store the object in a property. e.g. own[‘new_obj’] = #your new spawned object.

If you need to store many objects, store it in a list. e.g. own[‘obj_lst’] = [’#your objects here’]

Don’t use object ID(python ID) if you spawn many objects as it may not work. (try to spawn 10 objs several times to prove it)

Need to get back to worldcup fever, see ya!

Ok, so far I am now able to add objects with the same name and refer to them individually, which is great. Thanks everyone so far.


own['object1'] = scene.addObject("PlayerBounds",spawnLocation)
own['object2'] = scene.addObject("PlayerBounds",spawnLocation)

However I now have a new problem. The object has about 13 children. If I spawn the parent they spawn the children, which is fine. How do I refer to each children? There will be lots of the same children from different parents (“PlayerBounds”).

I think Monster may have tried to steer me to a solution earlier, although I don’t really understand, or know how to implement it.

B=own[‘object1’]
ChildList=B.children

I think you get it now, but I suggest to avoid such indexed names. It is a sign that you need a different data structure.

You have multiple objects of the same type? Place it in a container. What is a container? a list, a map …


addedObjects = []
addedObjects.append(scene.addObject( ... ))

You already know it, but it seems you do not have it in your thinking (right now).

After finding the object you where searching for (above posts), you can use the found object. BluePrintRandom showed you an example:


objectsChildren = object.children
allMyChildren = object.childrenRecursive

Think in KX_GameObjects! Check the BGE API what they can provide and what they can do. They are clever objects and can do a lot :D.

Thanks BluePrintRandom, that worked for me and I was able to get everything working last night, was up till 5am, but got it all working!

I’m away from my computer with the blends on it, but I will update my original post with an exact solution, although it isn’t neccesarily pretty or good coding practice.

@Monster: I’m unsure what you meant about avoiding indexed names? Do you mean like ‘Object1’, ‘Object2’? In my blend they are named differently, (‘forearmLeftBox’, ‘bicepLeftBox’,‘ChestBox’, ‘forearmRightBox’, etc) however I still think you’re right about needing a different data structure.

I will have to learn to think in KX_GameObjects definately, I’m struggling along with coding I think I have more of a flaky arty fart brain than a coder’s brain, but I’m not giving up or anything.

Anyway thanks for everyone’s help, very much appreciated. I got where I wanted to get. Once I get back to my usual machine I’ll update the original post and mark as solved probably this evening when .

Yes, this is what I mean. I know that your code is just a snippet. You can see in a lot of threads that people use this naming in production code, which makes it pretty dirty. The names you mention make a lot of sense and are perfectly fine :yes:.