[SOLVED] Collision() not being called

Hello! I am creating a simulation of stars and planets using jMonkeyEngine 3.1.0. I would like to detect when two objects collide. I have looked all over and I feel like my code is right but the collision() method is never being called - even when I clearly see the two objects collide.

I have my planets/stars behaving correctly and moving correctly. I see the Sun and the user created object collide on screen, and again, I simply don’t see the collision() method being called.

If anyone could look at my code and let me know what I am missing, I would really appreciate it! Hopefully I have overlooked something obvious.

Here are the relevant code blocks:

public class Main extends SimpleApplication implements PhysicsCollisionListener, PhysicsTickListener
{
    // Game related variables
    private Boolean              isRunning=true;
    
    private NBodySystem          bodies;
    
    private Geometry             sunGeo, saturnGeo, uranusGeo, neptuneGeo, userGeo = null;
    private Sphere               sunMesh, saturnMesh, uranusMesh, neptuneMesh, userMesh;
    private Spatial              jupiterMesh;
    
    private RigidBodyControl     sunPhysControl, userPhysControl;
    private SphereCollisionShape userCollisionShape, sunCollisionShape;
    
    private ParticleEmitter      jupiterTrailEmitter, saturnTrailEmitter, uranusTrailEmitter, neptuneTrailEmitter, sunTrailEmitter, userTrailEmitter;
   
    private float                zoom = 1.05f;
    private float                camZ = 10.0f;
    
    private Boolean              userCreated = false;
    
    /** Prepare the Physics Application State (jBullet) */
    private BulletAppState bulletAppState;
    
        public static void main(String[] args) 
        {
            Main app = new Main();
            app.start();
        }
        @Override
        public void simpleInitApp() 
        {
            // Set up Physics
            bulletAppState = new BulletAppState();
            stateManager.attach(bulletAppState);
            bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0, 0, 0));
            bulletAppState.getPhysicsSpace().addTickListener(this);
            bulletAppState.getPhysicsSpace().addCollisionListener(this);
            bulletAppState.setDebugEnabled(true);

            // Setup the Sun
            sunMesh = new Sphere(32, 32, 0.10f);
            sunGeo = new Geometry("Sun", sunMesh);
            Material sunMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
            sunMat.setBoolean("UseMaterialColors",true);
            sunMat.setColor("Diffuse", ColorRGBA.Yellow);
            sunMat.setColor("Ambient", ColorRGBA.Yellow);
            sunMat.setColor("GlowColor", ColorRGBA.Yellow);
            sunGeo.setMaterial(sunMat);
            sunGeo.setLocalTranslation(0.0f, 0.0f, 0.0f);
            rootNode.attachChild(sunGeo);
        
            sunCollisionShape = new SphereCollisionShape(0.10f);
            sunPhysControl = new RigidBodyControl(sunCollisionShape, 1f);
            sunGeo.addControl(sunPhysControl);
            bulletAppState.getPhysicsSpace().add(sunPhysControl);

            userMesh = new Sphere(24, 24, 0.07f);
            userGeo = new Geometry("user_planet", userMesh);
            Material userMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
            userMat.setBoolean("UseMaterialColors",true);
            userMat.setColor("Diffuse", ColorRGBA.Green);
            userMat.setColor("Ambient", ColorRGBA.Green);
            userGeo.setMaterial(userMat);
            userGeo.setLocalTranslation((float)p.x, (float)p.y, (float)p.z);
            rootNode.attachChild(userGeo);

            userTrailEmitter = CreateEmitter();
            rootNode.attachChild(userTrailEmitter); 
            
            userCollisionShape = new SphereCollisionShape(0.10f);
            userPhysControl = new RigidBodyControl(userCollisionShape, 1f);
            userGeo.addControl(userPhysControl);
            bulletAppState.getPhysicsSpace().add(userPhysControl);

        }

    public void simpleUpdate(float tpf) 
    {
        int num = bodies.getNumBodies();
        // num = 5;

        bodies.advance(0.01);
        
        NBody nb;

        for(int i=0; i<num; ++i) 
        {   	
            nb = bodies.bodies.get(i);
            
            float pX = (float)nb.x;
            float pY = (float)nb.y;
            
            zoom = .125f;
            
            pX = pX * zoom;
            pY = pY * zoom;
            
            if(i == 0 && sunGeo != null)
            {
                sunPhysControl.setEnabled(false);
                sunGeo.setLocalTranslation(pX, pY, 0f);
                sunPhysControl.setPhysicsLocation(new Vector3f(pX, pY, 0f));
                sunPhysControl.setEnabled(true);
                sunTrailEmitter.setLocalTranslation(pX, pY, 0f);
            }
            
            if(i == 1)
            {
                jupiterMesh.setLocalTranslation(pX, pY, 0f);
                jupiterTrailEmitter.setLocalTranslation(pX, pY, 0f);
            }

            if(i == 5 && userGeo != null)
            {
                userPhysControl.setEnabled(false);
                userGeo.setLocalTranslation(pX, pY, 0f);
                userPhysControl.setPhysicsLocation(new Vector3f(pX, pY, 0f));
                userPhysControl.setEnabled(true);
                userTrailEmitter.setLocalTranslation(pX, pY, 0f);
            }
        }
    }

   @Override
    public void prePhysicsTick(PhysicsSpace space, float tpf) {
        //System.out.println("PreTick!");
    }

    @Override
    public void physicsTick(PhysicsSpace space, float tpf) {
        //System.out.println("Tick!");
    }

    @Override
    public void collision(PhysicsCollisionEvent event) {
        System.out.println("Colission detected!");
    }
}

I can’t find anything wrong with your code, maybe a video would be helpful. On a side note, try calling the super methods in the tick methods and see what that does.
EDIT: Use the warp() method on the physics controls instead of enabling and disabling it. The collision might occur in the timeslot when the object is disabled. Anyway, why are you moving it that way? I’d probably use a bettercharactercontrol and set the walk direction.

First I would like to thank you for taking the time to reply! It is much appreciated.

I don’t have a video recorder installed but something I just noticed is that when the program starts, the physics debug wireframe is pink (or magenta - not sure which) and after a few seconds it turns blue and stays blue. This happens to both objects.

I can also confirm that prePhysicsTick() and physicsTick() are both called - just not collision.

What super methods should I try calling in the tick methods?

Also, I’m not sure I can use warp() since I am not using a player control. The reason I am moving the objects as I am is that I have an NBody class I am using to calculate an object’s position by simulating gravity between all of the bodies.

Any other thoughts?

1 Like

One more note - in my previous post, I mentioned that the debug wireframe starts as pink (or magenta) and turn blue after a few seconds.

I just discovered that if the objects collide when they are pink (or magenta), the collision() method is triggered! :slight_smile:

But after the wireframe turns blue, collisions are not detected.

Any ideas why the wireframe would be turning blue (perhaps going inactive?)

Thanks again!! After several night’s work, I feel like I’ve made at least a little progress this afternoon!!

2 Likes

The physics debugger uses pink for character controls, magenta for vehicles and “active” rigid bodies, and blue for “inactive” rigid bodies. If you’re seeing a debug object change from magenta to blue, then it’s likely a rigid body that’s gone inactive.

One possibility is that the object’s sleeping thresholds are set too high. As an experiment, you might try setting them to 0.

1 Like

You were right!!! :slight_smile:

Turns out if I run physControl.activate() regularly, the objects don’t turn blue and the collisions are reported as expected!

Thank you both for helping me figure this out!! It feels wonderful to make progress after several nights of beating my head against a wall! :smiley:

2 Likes

Just looked at the code again, try using setPhysicsLocation(), which is the warp() equivalent of RigidBodyControl.