Aiming at the 3D coordinate of where the aiming reticle is pointing at in 3rd person

Godot Version

4.2.1

Question

In the 3rd person view, the camera looks at the player character holding a gun and the player looks away from the camera with gun looking at the player HUD’s “center” reticle.

When I shoot the gun, the bullet will be instantiated from the gun and go outward. Right now, using 2 3DMarkers’ coordinates, I could make the bullet launched from the gun, but then the gun is not pointing exactly at where the camera is looking.

The 3D line that points outward from the camera and the 3D line that points outward from the gun are parallel to each other, so the bullet will not land exactly on the reticle. See this image as an example and imagine the long rectangle is a gun. Imagine if the crosshair at the center of the screen is a head of your enemy, but your “headshot” will miss because the gun is currently following the angle of the camera but the bullet will not land on where it supposed to land:
currentProblem

What would be a fair and an appropriate way to address this problem? Below is what I wanted. I believe I must know first, is there any object that is on the player’s reticle. After that, I need to know the 3D coordinate that the reticle lands on, so I could make the gun look_at it so the instantiated bullet could hit the spot:

wantThis

I read this twice but can’t form an image of what you mean. Scribble a picture, maybe?

There is a cool method on Transform3D called looking_at which may help you (also it will drive you to the edge of madness, but one must persevere)

Just in case:


var A := $Gun # NB it needs to be pointing down the -Z axis.
var B := $Reticle

var t = A.transform

# The all important Uppish var! It points kind of up as best it can based
# on where A is in space
var uppish:Vector3 = (t.basis.y + t.basis.z).normalized()

t = t.looking_at(B.position, upish) # update the transform!

A.transform = t # might need to do this, can't recall

# Now A should be looking towards 

@dbat I have drawn some diagrams for this and have updated the question. Could you please read the question 3rd time?

I believe I just need to get the 3D coordinate of where the center of the screen (the player’s reticle) lands on in order to have the gun look_at that coordinate. The question is how can I obtain that 3D coordinate?

The simplest way is to fake it. Unless you’re creating a real-world simulation, your game doesn’t have to be completely realistic. They are meant to be fun, and trading a little realism for ease of implementation is acceptable.

You can use your camera to aim, then have the gun pretend to fire at the position looked at by the camera, but have the bullet actual originate from your camera. Even some AAA games do this.

2 Likes

Ah. You want to look into “picking” (which is mouse-over really, on nodes or the collision shapes, whatever) to find the object the reticle is over.

But @soapspangledgames (cool name!) is right. Do it simple-stupid, at least at first.

Reticle is probably a Vector2 ui node. Just make a Vector3 at (Reticle.position.x, Reticle.position.y, -500) so bullets fly 500 units into the screen.

You can then mess with bullet drop and so on.

hth?

1 Like

@dbat @soapspangledgames Thank you for your responses and your suggestion for simplicity. However, I have found what I needed: Ray-casting — Godot Engine (stable) documentation in English

I created a Marker3D under Camera3D and placed it extremely far away from where the camera is looking at. Wherever the camera is looking, the Marker3D will follow at extremely far away place. It’s like having a pole of infinite length sticking out from the camera and at the end of the pole is the Marker3D, and we always know the position of the Marker3D.

Using Ray-Casting, I will know whether there is any object obstructing between the camera3D and the marker3D, and I will get the position of the intersection. For simplicity, I now set the position of a MeshInstance3D called “hitMarker” to be at the intersected position. This way, I got a 3D visual guide for the 3D intersected position.

My code is this:

var space = get_world_3d().direct_space_state
	
var global_target_position = Marker3D_for_raycast.global_transform.origin
var query  = PhysicsRayQueryParameters3D.create(
	camera3D.global_transform.origin,
	global_target_position,
	collision_mask,
	[self]
)
	
var result = space.intersect_ray( query )
	
if result:
	hitMarker.set_global_position( result.position )
else:
	hitMarker.set_global_position( Vector3(99999,99999,99999) ) # for hiding hitMarker

And because we now know the position of where the camera is looking at, we can use the function look_at and have the gun points at the intended intersected position.

1 Like