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:
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:
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.
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.