Think about a mechanic like in Pokemon Snap where you take a photo of a monster. When taking the photo, I want to know the offset from the center of the monster to measure the acuratcy of the player.
The monster most times , but not exclusively, has a spherical collisionshape. The center of the monster is therefore determined by a seperate “Focus” Node3D which is just there for positional means.
Think of this structure:
Photo ← script is here
Monster
So when I “take a photo” the ray may be on the outer edge of the sphere when viewed from the camera, far away from the monster center. How could I rate the accuracy of the player?
I can’t wrap my head around it. Something like get the positions in local coordinates as from the ray?
All I got so far is this:
var distance: float = 0
var ray_collision_object: Area3D = snapshot_ray.get_collider()
var ray_collision_point: Vector3 = snapshot_ray.get_collision_point()
var monster_center: Vector3 = ray_collision_object.get_node("../Focus").position
print(ray_collision_point.distance_to( monster_center )) // won't give correct results, as the hit point could be far in front of the Focus
I think it’s easiest to do in screenspace instead of worldspace. Unproject the targets position and calculate the distance to viewport center:
func dist_to_view_center(pos):
var viewport = get_viewport()
var cam = viewport.get_camera_3d()
var view_center = viewport.get_visible_rect().size / 2.0
var screenpos = cam.unproject_position(pos)
var dist_to_center = screenpos.distance_to(view_center)
print(dist_to_center)
return dist_to_center
Pass the targets global_position to that function and it returns the distance in pixels. There’s just one problem: viewport resolution would affect gameplay. So you might want to divide screenpos by resolution to make it the coordinates work same on everyones machine:
func dist_to_view_center_v2(pos):
var viewport = get_viewport()
var cam = viewport.get_camera_3d()
var view_size = viewport.get_visible_rect().size
var screenpos = cam.unproject_position(pos) / view_size
var view_center = Vector2(0.5, 0.5)
var dist_to_center = screenpos.distance_to(view_center)
print(dist_to_center)
return dist_to_center
Like this the coordinates go from 0.0 to 1.0, instead of whatever the resolution is. Center of the viewport is (0.5, 0.5).
If distance is bigger than 0.5, target point is out of view.
Thanks. I didn’t know about the unproject_position function. It is so simple if you know you can just use the “screenshot” coordinates for calculations. Your suggestion about the followup percentage was also a good prediction