[SOLVED] Shooting Raycast center inaccurate on Mobile

Hello,

I have game like this drag screen which rotates camera then shoot planes, boxes… as shown in image…

Every time you shoot msg appears in console which mentions where you hit… And which works great on pc…
But it is not working accurately on mobile device…

Here is the project link…
https://playcanvas.com/project/802087/overview/mobile-raycast-center-issue

Here is the snippet…

CameraController.prototype.doRayCastToCenter = function () {
    
    
    // var screenPosition = new pc.Vec3(this.app.graphicsDevice.width / 2, this.app.graphicsDevice.height / 2, 0);
    // var from = this.entity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.entity.camera.nearClip);
    // var to = this.entity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.entity.camera.farClip);

    
    var screenCenterX = (this.app.graphicsDevice.width / 2) / window.devicePixelRatio;
    var screenCenterY = (this.app.graphicsDevice.height / 2) / window.devicePixelRatio;
    var from = this.entity.camera.screenToWorld(screenCenterX, screenCenterY, this.entity.camera.nearClip);
    var to = this.entity.camera.screenToWorld(screenCenterX, screenCenterY, this.entity.camera.farClip);
    
    var result = this.app.systems.rigidbody.raycastFirst(from, to);
    
    console.log(result);
    if (result)
    {
        var pickedEntity = result.entity;
        
        console.log("hit success = ",pickedEntity);
    }
    else
    {
        console.log("hit Failed");
    }
    
};

I think it was working great on mobile device as well before few months back… :thinking:

Not sure any update cause issue or what…
Any help will be really appreciated!

Thank you

Hi @Ketan_ATA,

The reason is that you have set your game to use a fixed resolution of 1280x720. So your code here always reports that, even though the window may be upscaled or downscaled:

    var screenCenterX = (this.app.graphicsDevice.width / 2) / window.devicePixelRatio;
    var screenCenterY = (this.app.graphicsDevice.height / 2) / window.devicePixelRatio;

Not sure what’s the correct way to calculate the 2D coords for screenToWorld, but I think you need to take into account how the canvas stretches?

An easy fix if that accommodates your use case is to set Resolution Mode to Auto:

image

Your aspect ratio will remain the same, and you will get better graphics in bigger screens. That fixes raycasting in your sample project.

3 Likes

@Leonidas Thank you very much for replay… :slightly_smiling_face:

I also checked your Forked project : https://playcanvas.com/project/803760/overview/mobile-raycast-center-issue

I run the game directly from your fork project… on chrome (used toggle device toolbar option)

But unfortunately the issue is still there…
And I try to shoot this 1st plane but everytime it shows hit failed :thinking:

Yeah, right, for displays with larger than 1 pixel density you don’t need to take that into account for the screen coords to work, simplify lines 200/201 and it will work:

    var screenCenterX = (this.app.graphicsDevice.width / 2);
    var screenCenterY = (this.app.graphicsDevice.height / 2);
1 Like

@Leonidas Thank you very much! Works great now… :smiley: :love_you_gesture:t2:

So according to it…

Will it work everywhere? I mean game will work everywhere on pc and mobile?
Or do i need to modify anything else apart from this in the code?

I am fairly certain the you don’t need the actual physical size of the display, but the web resolution to get screen to world to work. I feel you are good to go, just make sure to run some tests in multiple devices to confirm that :innocent:

1 Like

@Leonidas Thank you very much again! :smiley:

Posting working snippet here just in case…

CameraController.prototype.doRayCastToCenter = function () {
    
    var screenCenterX = (this.app.graphicsDevice.width / 2);
    var screenCenterY = (this.app.graphicsDevice.height / 2);
    var from = this.entity.camera.screenToWorld(screenCenterX, screenCenterY, this.entity.camera.nearClip);
    var to = this.entity.camera.screenToWorld(screenCenterX, screenCenterY, this.entity.camera.farClip);
    
    var result = this.app.systems.rigidbody.raycastFirst(from, to);
    
    console.log(result);
    if (result)
    {
        var pickedEntity = result.entity;
        
        console.log("hit success = ",pickedEntity);
    }
    else
    {
        console.log("hit Failed");
    }
    
};

Issue is solved!

1 Like