- Home /
Ray picking objects with a 'Curved World' Shader
Hi
I am creating a game with a curved world and use the shader from https://alastaira.wordpress.com/2013/10/25/animal-crossing-curved-world-shader which works really fine. My problem is that Raycasts do not hit objects as their real position is a bit higher than their visual appearance (as they are warped down depending on distance).
How can I modify the mouse picking to account for this effect? Maybe a custom Projection Matrix for the Camera, but math like this is beyond my knowledge.
Any hints are appreciated.
Hi. Yes, this is going to be a problem: the shader is an entirely visual effect - it has no effect on collider boundaries or raycasts, say - and it's performed in camera space. Adjusting for arbitrary linear raycasts in the world to match that would be very hard indeed.
What's your use case exactly? If you could reduce the problem domain slightly (say, you were only using raycasts based on the mouse cursor position, and hence already aligned to camera-view) it might be possible to come up with a suggestion.
Hi tanoshimi. I have a world with objects and units on it (basically a strategy game). The entire game area should be a planet, hence the curved world shader (I tried with a sphere object as a world before, but that is even more complicated with my use cases). Units are selected with the mouse and that is my problem at the moment. Is it possible to write a custom pick function where the ray is going in the inverse-curved direction as the shader? I know the curve function at least.
See "Populous The Beginning" images for the game that inspired me.
Answer by KirschiX · Jan 03, 2017 at 07:34 PM
After some thinking I came up with this solution by adjusting the original RaycastHit by the inverted curvature factor. Two downsides that are yet to be worked out are that it is not perfectly accurate as I had to tweak the curvature factor from 0.023f in shader to 0.03f in c# code. And clicking the "sky" is still picking terrain that is far off in the distance. But other than that it is working pretty good.
private RaycastHit? adjustHit(RaycastHit hit)
{
var pt = hit.point;
var dist = hit.distance;
Vector4 vv = new Vector4(pt.x, pt.y, pt.z, 1.0f);
vv.x -= Camera.main.transform.position.x;
vv.y -= Camera.main.transform.position.y;
vv.z -= Camera.main.transform.position.z;
// Increase y by curvature factor (originally -m_Curvature)
vv = new Vector4(0.0f, ((vv.z * vv.z) + (vv.x * vv.x)) * m_Curvature, 0.0f, 0.0f);
var finalVec = new Vector3(pt.x, pt.y + vv.y, pt.z);
// Send raycast again by finding screen pos of world position hit
RaycastHit hit2;
var screenPos = Camera.main.WorldToScreenPoint(finalVec);
var ray = Camera.main.ScreenPointToRay(screenPos);
if (Physics.Raycast(ray, out hit2, 100f))
{
return hit2;
}
return null;
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
getting center of rotated object 0 Answers
Reverse object position order 1 Answer