[SOLVED] Select entity that is in the center of the screen using pc.Picker?

It’s a little hard to understand how pickers work, this is the basic code I’ve found which is not very accurate in my case (3rd view + first person game)
Why does it happen? Looking at one entity - outputs other


Logs ground
But if I move screen a little more to the bottom it works as it should
For the lantern in example, it is very accurate

PickerFramebuffer.prototype.initialize = function() {
    // Create a frame buffer picker with a scaled resolution
    var canvas = this.app.graphicsDevice.canvas;
    var canvasWidth = parseInt(canvas.clientWidth, 10);
    var canvasHeight = parseInt(canvas.clientHeight, 10);
    
    this.picker = new pc.Picker(this.app, canvasWidth * this.pickAreaScale, canvasHeight * this.pickAreaScale);
    this.layers = [];
    for (var i = 0; i < this.layerNames.length; ++i) {
        var layer = this.app.scene.layers.getLayerByName(this.layerNames[i]);
        if (layer) {
            this.layers.push(layer);
        }
    }
    
    this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onSelect, this);
    
    this.on('destroy', function() {
        this.app.mouse.off(pc.EVENT_MOUSEDOWN, this.onSelect, this);
    }, this);
};

PickerFramebuffer.prototype.onSelect = function (event) {
    var canvas = this.app.graphicsDevice.canvas;
    var canvasWidth = parseInt(canvas.clientWidth, 10);
    var canvasHeight = parseInt(canvas.clientHeight, 10);

    var camera = this.entity.camera.camera;
    var scene = this.app.scene;
    var picker = this.picker;

    picker.resize(canvasWidth * this.pickAreaScale, canvasHeight * this.pickAreaScale);
    picker.prepare(camera, scene, this.layers);

    // Map the mouse coordinates into picker coordinates and 
    // query the selection
    var selected = picker.getSelection({
        x: Math.floor(event.x * (picker.width / canvasWidth)), 
        y: picker.height - Math.floor(event.y * (picker.height / canvasHeight))
    });

    if (selected.length > 0) {
        // Get the graph node used by the selected mesh instance
        var entity = selected[0].node;

        // Bubble up the hierarchy until we find an actual Entity
        // that has the script we are looking for
        while (entity !== null && !(entity instanceof pc.Entity) && (entity.script && entity.script.pulse)) {
            entity = entity.getParent();
        }
        if (entity) {
            console.log(entity._parent);
        }
    }
};

My goal is to select entity that is in center of the screen everytime
Would (canvas.clientWidth/2); work?

Turns out screentoworld was a better solution to use
I’m using this to raycatstall and pick a closest entity on click, while ignoring those I don’t need like a player or ground or etc, you can easily edit it for your needs

var closestLadder = null;
var closestDistance = 10;
var width = pc.app.graphicsDevice.canvas.clientWidth;
var height = pc.app.graphicsDevice.canvas.clientHeight;
var start = this.entity.camera.screenToWorld(width/2, height/2, this.entity.camera.nearClip);
var end = this.entity.camera.screenToWorld(width/2, height/2, this.entity.camera.farClip);
this.app.systems.rigidbody.raycastAll(start, end).forEach(function (result) {
    result.entity.forEach( function(result){
     if (result.enabled && result.state == "Loaded") { //Change this line to suit your needs
        var distance = playerPosition.distance(result.getPosition());
        if (distance < closestDistance) {
            closestDistance = distance;
            closestLadder = result;
        }
     }
 }.bind(this));
});

console.log(closestLadder);

We can mark this as solved

2 Likes