Name 'worldNP' is not defined

Hello everyone,

I am trying to get an answer on Stack Overflow towards this issue. So far, nobody was able to answer this question. I decided to ask here since this is a forum for Panda3D.

Full details are in the provided hyperlink. In short, I am trying to do character movement from the provided code example on Panda3D’s manual towards their Bullet Physics engine. I have gotten a world set up, but it throws me an error about worldNP. I have not went through the entire document, but a quick search indicates that worldNP is only dealt with their Bullet Physics engine.

Hi and welcome.

You are mixing paradigms in your code and it isn’t complete.

self.worldNP is never defined and self. would imply that it would be a member of a class. You are not defining this inside a class, so the self. part shouldn’t be there. Also you have to define the NodePath that holds your physics world (that is that missing worldNP) and attach it to the scenegraph (usually the render node).

All that is explained in the manual, try to read through the manual carefully and also try to brush up on your Python skills.

To elaborate a little on what tcdude said above, “self” is the conventionally-used name for a special parameter that’s automatically passed into methods belonging to instances of classes. It stores a reference to the instance, allowing the developer to access the variables and methods of that instance.

For example:

# A simple class.
# Note the use of the "self" parameter below.
class Cat():
    # The initialisation method
    def __init__(self):
        self.sound = "Meow"

    def mew(self):
        print (self.sound)

cat = Cat()
cat.mew() 
# Note that the "self" parameter is >not< passed in above!
# It's automatically provided, since this method is being called
# from a class-instance.

[edit]
Looking over the manual pages, it does look as though they indeed don’t clarify where “worldNP” comes from, which may confuse those not already familiar with object-oriented Python. Those pages could perhaps use some touch-ups to make them clearer, I think.

Thank you @tcdude. Your explanation have led me to investigate more about self.worldNP. I was able to get worldNP to work by defining what shape the world is. For anybody else that is having the same issue, I wrote the following code when doing world declaration:
Imports -

from panda3d.core import Vec3
from panda3d.bullet import BulletWorld
from panda3d.bullet import BulletBoxShape
from panda3d.bullet import BulletRigidBodyNode

Within the class initalization. Game(ShowBase) for example:

                self.world = BulletWorld()
                self.world.setGravity(Vec3(0, 0, -9.81))
                shape = BulletBoxShape(Vec3(30, 30, 30))
                node = BulletRigidBodyNode('World')
                node.addShape(shape)

                self.worldNP = render.attachNewNode(node)

Thanks for elaborating on how self. is used. On the side side, I am thankful that I am not the only one that thinks for that particular section in Panda3D manual did not discribe about worldNP.

I ran into this same exact problem. I am very used to the “self.” not defined issue. Just delete it.

I felt the need to comment on the above solution because I don’t think “world” needs a defined shape. Please correct me if I am wrong.

Setup the bullet world

world = BulletWorld()
world.setGravity(Vec3(0, 0, -9.81))
node = BulletRigidBodyNode(‘World’)
worldNP = render.attachNewNode(node)

Well, without a shape, there’s presumably no environment for the character or other objects to collide with, whether to stand upon or to block movement.

I was under the impression that “world” is just setting up the BulletWorld environment. I create a “plane” for people to stand on. That is how I interpreted the documentation.

However, I can see how giving the world a shape feels more logical. Just not required.

If I was creating an RPG world with multiple terrains for different scenes, then I would create multiple terrain nodes as needed. I can see the point if there was only one scene, then it is logical to assign the shape directly to the “world” node. I don’t think there is a right or wrong with this issue.

The nomenclature used in the sample is perhaps a bit misleading: “self.worldNP” is a thing separate from “self.world”: as I’m reading the above, the latter is indeed just the BulletWorld environment, while the former is just an arbitrary piece of geometry, much like the plane that you describe.

The “self.worldNP” variable could easily be called something like “self.levelCollider”.

In short, the sample is doing pretty much what you describe with your plane for people to stand on, I believe.

So, in a sense you’re right: there’s no need to give a shape to the BulletWorld object itself–but conversely, the sample isn’t doing that. (And indeed, I’m not sure that such a thing is offered by BulletWorld.)

I actually just hit this section of the tutorial today. I still don’t like the recommended solution. Why? Because the code samples are not consistent. Most of the other code samples use “render”. Therefore, instead of trying to define “self.worldNP”, change it to “render”.

npA = render.attachNewNode(BulletRigidBodyNode(‘A’))

There are advantages to using a separate NodePath–it can allow one to make large-scale modifications without affecting everything, and makes it easier to remove the whole thing (such as for unloading the current level ahead of loading a new one).