Hello Picking Strange Behavior

I am trying to add hitscan guns, to my first person shooter, and to do this, I borrowed code from the Hello Picking example on the wiki.

if (shoot){
  // 1. Reset results list.
        CollisionResults results = new CollisionResults();
        // 2. Aim the ray from cam loc to cam direction.
        Ray ray = new Ray(cam.getLocation(), cam.getDirection());
        // 3. Collect intersections between Ray and Shootables in results list.
      
        rootNode.collideWith(ray, results);
       
        // 5. Use the results (we mark the hit object)
        if (results.size() > 0) {
          // The closest collision point is what was truly hit:
          CollisionResult closest = results.getClosestCollision();
          // Let's interact - we mark the hit with a red dot.
          mark.setLocalTranslation(closest.getContactPoint());
          rootNode.attachChild(mark);
        } else {
          // No hits? Then remove the red mark.
          rootNode.detachChild(mark);
        }
      
         
  }

This code attaches a red marker to the root node, so that it is touching solid objects, and in the direction you are pointing.

However, a strange issue occurs, that when you face the same direction, and hold down the shoot button, the red dot is placed in the correct spot, but then starts to glide towards the camera.

Anyone know what causes this?

1 Like

You mean, as if the next firing is hitting the last one and so on? ie: you are putting the red box at the intersection of your last box?

1 Like

That is very likely the cause, i suppose i will have to make the mark count as a non colladable object to fix this.

1 Like

“non-collidable” just means that you skip it in results… which means you can no longer always just get the closest one.

Alternately, you can use a more advanced picking system where you add listeners to the things you want to pick (or their root/parent). Lemur includes such a picking system and it can be used without the rest of Lemur.

1 Like

How can i remove the mark from the results then? As far as I can see, there is no direct method of doing this.

1 Like

There are a multiple direct methods.

First of all, you use the rootNode:
rootNode.collideWith(ray, results);
In an ideal situation you’d split collidables and non-collidables in different Nodes.

Also, you use:
results.getClosestCollision();
Which gets the closest result, always. To get the preferred result you can iterate through results and pick out what you need.

1 Like

You iterate over the results and skip the ones you aren’t interested in.

1 Like

Or dont put it in the same node as the collidables. Then it will never collide.

1 Like

Alright, thanks for your ideas, you have been very helpful. I’ll try this over the weekend.

1 Like

Ok, I did what @jayfella said, and I added 2 different nodes that are childs to the root node, one for interactable objects like models, and another for aesthetics like skybox and water. Light is attached to the root node, so it effects everything.

 if (shoot){
  // 1. Reset results list.
        CollisionResults results = new CollisionResults();
        // 2. Aim the ray from cam loc to cam direction.
        Ray ray = new Ray(cam.getLocation(), cam.getDirection());
        // 3. Collect intersections between Ray and Shootables in results list.
        
        World.collideWith(ray, results);
       
        
        // 5. Use the results (we mark the hit object)
        if (results.size() > 0) {
      // The closest collision point is what was truly hit:
      CollisionResult closest = results.getClosestCollision();
      // Let's interact - we mark the hit with a red dot.
      mark.setLocalTranslation(closest.getContactPoint());
      NonWorld.attachChild(mark);
    } else {
      // No hits? Then remove the red mark.
      NonWorld.detachChild(mark);
    }
1 Like