3D 3rd Person shooter, aligning different guns to reticle

Godot Version

4.7 stable

Question

I want am making a 3rd person shooter and I want to set up aiming at the reticle. I got IK to target and follow as I want for the hand of the model but naturally guns don’t shoot from the hand and using a quick test pistol the aim can get really off.

My main goal (in the event my approach is convoluted and stupid) is to have a set up where animations are blended some with IK to allow for free aiming at the reticle from them. Different weapons can also be swapped out and weapons will still aim correctly at the reticle to fire from directly. (As in I want a firearm model specific point to fire the bullets not some other space) This is also important for a first person setting to be implemented later. (or not as it can be scrapped if it doesn’t work out or is too much work)

What I have tried so far is mostly setting up a raycast on a test gun a pistol and trying to get it to aim at the reticle or be consistently somewhat off I can dial in. I can’t seem to manage it along with the joint constraints I will need at the same time. As I end more eventually it gets to where the end bone just rotates the rest of the way and it does like a 90 degree angle at the end. I have a subset of bones, parented but disconnected from the main hand bone, which i use for finding the placement of the gun’s barrel yet i can clearly see the path the IK is taking in green does not line up with those bones. i have gotten decently close with JacobianIK but it ends up being very jittery. Either I am misunderstanding the joint limit cones (the wireframe being the excluded rotations is my understanding), its what I think that the more limits it just decides to pivot the point best it can, something i don’t want since i just want it to go straight and let the earlier bones set it’s angle up. For more clarification on the barrel bones coming from the hand, its 2 bones in parallel from the hand bone off set to the side where it would be in relation to the hand when held. At this point I am just burned out spending all day messing with it.

Considering I am still struggling with this (I have made some headway with CCDIK by freezing the hand bone too so only the arms can actually pose at all, with their limits. But still kind of icky, but at least its not shaking to the point the gun wouldn’t realistically remain held.) and eventually will need to anyway I have begun to try and work out rotating the torso to cursor too. This also does not work right. SkeletonIK node has the proper controls with the IK target (the rest bend to it so trying to have the spine rotate to the target, has it arc forward and restricting it just keeps it to a lean which is not what I want.) but similar to above but worse IT ONLY rotates the end bone. meaning a chain from the hips to the head will just see the head spin. lack of limitations also is an issue but I can account for that with code. I am thinking of trying out an unorthodox way of doing my bones to try and deal with this but it shouldn’t be needed as the only thing unordinary about my model is each bone has one segment that is fully weighted to it due to it being mechanical. So it has 0 deformation so when other tutorials show a rig doing just the chest and you get a proper spine curve it may simply be like for me, only the upper bone is moving but because of the deformation and weight painting, the curve still exists. that said I may have to just write my own combination of SkeletonIK and JacobianIK (Jacobian does get the right spinecurve and limits are nice, however configuring it just doesn’t seem right or requires something possibly more convoluted that trying to merge the two.)

I think you’re overcomplicating the aim part. Most games just fire the bullets out of the camera, and bullets from the gun are fake and drawn in with a shader.

Unless you’re making a milsim or a physics-based shooter where the bullets have to come out of the barrel of the gun, it’s good enough to just fake it and point the gun in the general direction of the target, and fire bullets out of the camera. If you’re struggling to make the player turn to even close to where the camera is aiming, then you might get away with just forcing the player to face the reticle with look_at(), which will force the model to turn and face the given point.

Granted, that;s a messy solution, and may mess with your IK, though it would work fine for testing as it would force your model to point at what you’re aiming at.

A series of LookatModifer3D nodes has gotten me through the torso issues. I can get the same kind of rotation I needed from SkeletonIK and the restrictions of the other IK systems. I wasn’t aware of it prior but looking into BoneModifier3D as a means of doing the arm ik without having to tear my hair out rewriting an IK system for my purposes. I will explain my current idea I haven’t gotten around to trying yet later.

The camera distance is too far for the bullets from camera to work, it would be very obvious in gameplay. Furthermore pretty much everything will be projectile based not hitscan. The real reason I need the guns to align and such is because the character will always be dual wielding. I guess the closest system would be Armored Core 4 Answer’s (can’t be certain about other AC games since I haven’t played them, but they seem on target) where the aim of the actual firearms matter, to the point you have secondary reticles letting you know if your arm is on target yet or not. So basically my approach is to mark a point in space using the camera as a reference (currently a raycast from the viewer and then either at a certain distance if no hit, or where it collides place the marker) for where to aim the weapons to and then fire from the weapons.

On to my current idea, I recognize the problem is the arm to hand chain will end at the target but not have the offset needed for the barrel which from some testing can lead to very off results. there can be some cheating but I need something consistent and reliable for implementing weapons with different offsets. (the height from the hand for a pistol and a bazooka might be very different.) And also be usable with different holds. a bazooka would be held against the shoulder while a pistol can be more freely handed. So finally to the idea, I know where I want to aim so I create a secondary point for the arm to track to, then rotate arm/hand (depending on hold) to angle the weapon properly. the secondary point will be offset from the actual aim spot by a distance dependent on the type of hold and angled a bit off. The angle of the hand will then be corrected using a point of reference shooting out from the bone (current plan is another bone I have just going in that direction), to compare the rotation of the line made by those two points with the desired one. Lastly I will cheat somewhat from here since it should be very close to accurate if not. Hopefully the idea and the soft math in my 10 remaining braincells works when i get the rest to try it with a fresh mind.

I am not good at vector math so I’ll just put this here while I’m out incase someone more knowledgeable comes around and figures it or a better way out.

What I am attempting to do here is get the rotation of the a secondary offset point that the hand is pointed at, to the main reticle ( I already have created a working and correct means of placing a marker3d node at that point for the hand to map to, accounting for stuff like its not just taking the global_position of the real target for guns and doing y-= 2.0, it scales depending on angle its being looked at from. ) and get the rotation of the hand bone to a point (I marked with a bone, so finding it regardless of the handbone’s rotation is easier) in the direction guns will extend their handle from. think thumbside of the hand. I want to then use this to figure out how to rotate the bone to make the two parallel, while keeping the hand pointing in the same direction. basically line from hand bone to offset point is the same with the ik aligned it to. the line from hand bone to the secondary bone shooting out where the gun be on top of the hand (its just straight out to the top side, not actually caring about the gun itself just to let me know the direction), and the line from the offset point and the real target are parallel with one another. and lastly directions of the offset marker and handbone to their respective second points are in the same direction. (one point isn’t extending left the other going right even though they are parallel still.) Probably didn’t explain it the best but here is what I got so far.

extends SkeletonModifier3D
class_name Aim_Offset_Correction_IK

@export var Hand_Bone :String
@export var Rotating_Bone :String
@export var Offset_Vector_Bone:String
@export var Real_target_marker:Marker3D
@export var Offset_vector_marker:Marker3D
@export var helper_marker:Marker3D
var skeleton :Skeleton3D

func _ready() → void:
skeleton=get_skeleton()

func _process_modification():
var Hand_Location :Vector3 = skeleton.to_global(skeleton.get_bone_global_pose(skeleton.find_bone(Hand_Bone)).origin)
var OVBone_location:Vector3 = skeleton.to_global(skeleton.get_bone_global_pose(skeleton.find_bone(Offset_Vector_Bone)).origin)
helper_marker.global_position=Hand_Location
helper_marker.look_at(OVBone_location)
Offset_vector_marker.look_at(Real_target_marker.global_position)
var correct_angle :Vector3 = Offset_vector_marker.global_basis.get_euler().normalized()
var current_angle :Vector3=helper_marker.global_basis.get_euler().normalized()
var proper_angle :Vector3 = correct_angle-current_angle
var Rbone_index = skeleton.find_bone(Rotating_Bone)
var bone_rotation: Quaternion = skeleton.get_bone_pose_rotation(Rbone_index)
var bone_parent_bones_rotation: Quaternion = skeleton.get_bone_global_pose(Rbone_index).basis.get_rotation_quaternion() * bone_rotation.inverse()
var skeleton_global_rotation: Quaternion = skeleton.global_transform.basis.get_rotation_quaternion()
var bone_parents_rotation: Quaternion = skeleton_global_rotation * bone_parent_bones_rotation
var bone_global_rotation: Quaternion = bone_parents_rotation * bone_rotation
var new_bone_global_rotation :Quaternion = Quaternion(Vector3.UP, proper_angle.y) * bone_global_rotation
new_bone_global_rotation = Quaternion(Vector3.LEFT, proper_angle.x) * new_bone_global_rotation
var new_bone_rotation: Quaternion = bone_parents_rotation.inverse() * new_bone_global_rotation
skeleton.set_bone_pose_rotation(Rbone_index, new_bone_rotation)

The Quaternion stuff is code I found online trying to figure out how to navigate the local global rotation mess I am going through, and is the least understood by me since I have yet to dig into rotation bones, via code yet.