Hitscan for Weapons not working

Godot Version

Godot 4.3

Question

Hi! So, let me explain a little bit. I’m following a tutorial on fps mechanics and i’m on this part where the gun shoots and the hitscan, which is used to calculate the point where the “bullet” hits, calculates where the shot landed. Problem is, i’ve followed everything and the hitscan doesn’t work. The game isn’t crashing, it isn’t even showing an error, it just does nothing as it was intended to do…

func Get_Camera_Collision()->Vector3:
   var camera = get_viewport().get_camera_3d()
   var viewport = get_viewport().get_size()
   
   var Ray_Origin = camera.project_ray_origin(viewport/2)
   var Ray_End = Ray_Origin + camera.project_ray_normal(viewport/2)*Current_Weapon.Weapon_Range
   
   var New_Intersection = PhysicsRayQueryParameters3D.create(Ray_Origin,Ray_End)
   var Intersection = get_world_3d().direct_space_state.intersect_ray(New_Intersection)
   
   if not Intersection.is_empty():
   	var Cel_Point = Intersection.position
   	return Cel_Point
   else:
   	return Ray_End
   
func Hit_Scan_Collision(Collision_Point):
   var Bullet_Direction = (Collision_Point - Bullet_Point.get_global_transform().origin).normalized()
   var New_Intersection = PhysicsRayQueryParameters3D.create(Bullet_Point.get_global_transform().origin,Collision_Point+Bullet_Direction*2)
   
   var Bullet_Collision = get_world_3d().direct_space_state.intersect_ray(New_Intersection)
   
   if Bullet_Collision:
   	var Hit_Indicator = Debug_Bullet.instantiate()
   	var world = get_tree().get_root()
   	world.add_child(Hit_Indicator)
   	Hit_Indicator.global_translate(Bullet_Collision.position)
   	
   	Hit_Scan_Damage(Bullet_Collision.collider)

func Hit_Scan_Damage(Collider):
   if Collider.is_in_group("Target") and Collider.has_method("Hit_Successful"):
   	Collider.Hit_Successful(Current_Weapon.Damage)

It could be the code i’m using where something doesn’t really input the hit from the hitscan but i kinda don’t think it is.

Also, i think it’s important to show the object that is being hit and that i want to do damage to see if the hitscan is really calculating something.

If anything, i posted here the project of my game, and if anyone wants to see for themselves, because maybe i just didn’t explain well enough…

I could also post the link to the youtube video if anyone wants, but i will leave at this for now. Any help is much appreciated

Have you tried adding print statements and debugging with breakpoints?

1 Like

Yes, and none returned something. There’s a print statement right by the function “Hit_Successful” of the object that i want to make my hitscan to collide with, but neither did this return something.

1 Like

I’m looking at these two statements and I think what this is trying to do is translate the rat that should be cast by the gun muzzle.

The issue here is when you add the Collision_Point+Bullet_Direction*2 it’s not going to give you an accurate representation to test the bullet path.

And bullet_direction is going to give you a vector in the opposite direction. I would try and reversing the bullet_direction after it’s normalized.

var Bullet_Direction = - (Collision_Point - Bullet_Point.get_global_transform().origin).normalized()

1 Like

Oh, so basically the shot is going the opposite way i want it to?

In this new update of the code you provided, the minus sign before “(Collision_Point…)” is what i need to add? Or there’s something more?

That’s because in the tutorial it said, sometimes, the bullet doesn’t really go where you want it to. So this part was to properly set it up so it hits the target. But maybe it wasn’t so necessary?

Sorry I’m thinking I’m mistaken, I didn’t wrap my head around it fully. I think it should work fine since you are only using positions, and not explicit angles. It should be okay.

I still think the direction needs to be reversed so it will actually hit the body on the second query.

Do you have a way of doing that, or is this what you talk about?:

I found the use for the negative sign before (Collision_Point) to be intriguing.

1 Like

Yes, but now that I think about it more I’m wrong on both counts. If we simplify to one axis and collision is 100 and bullet origin is 1.

The equation becomes 100 - 1 = +99. After normalizing to +1 the direction is correct.

Let me take a look at the project.

I figured out the problem.

func Get_Camera_Collision()->Vector3:
	var camera = get_viewport().get_camera_3d()

since your gun manager is a child of a subviewport:
image

The function get_viewport().get_camera_3d() is returning view_model_cam which is miles away in the scene. and will not hit anything.

to remedy i would add an export to select the camera for the weapons manager to use.


update

I tried updated the code to fix it by adding this which put the ray in the right position @export var camera : Camera3D, but i ran into a new issue.

The sub-viewport also has its own world 3d. so this world doesn’t contain the troll to hit

var Intersection = get_world_3d().direct_space_state.intersect_ray(New_Intersection)

image

My final suggestion is to remove the weapon manager from the subviewport. or have the viewports share the world. I tested removing the world3d form the subviewport and can now hit the troll, but there are visual issues.

update

I guess as a hack, after using the exported camera you could do camera.get_viewport(...) then you wouldn’t need to reorganize your subviewport.

So, i think it’s heading in a safe path, and before showing how i’ve done to get the “view_model_cam”, i’m just gonna ask:

As you said i could use camera_get_viewport( ) and not do all the rearranging, but how could i actually do that?

var camera = get_viewport().get_camera_3d()

Do i have to delete “.get_camera_3d( )”? Or change something else?

This is how i’ve done the exporting of the camera (sorry if i did it wrong, still getting used to this)

@export var camera : Camera3D

You need to manually assign the camera with this export variable.

Then when you go to use it

func Get_Camera_Collision()->Vector3:
   var viewport = camera.get_viewport().get_size()
 
   ...
   var Bullet_Collision = camera.get_world_3d().direct_space_state.intersect_ray(New_Intersection)
   ... 
  # then the rest of the code is the same
   
 

Whenever you need to use world3d use the camera form the export value.

Brother, the fact that everything that you said holds truth and there are no error or breaks, but still there seems that no bullet or hitscan signal is coming, lends me to the assumption that maybe i did something wrong and not enough code could solve it. I have an hypothesis tho:

See the “Bullet_Point”? This is the way that spawns the hitscan to calculate the direction and hit of the bullet. In the tutorial, it was clear 2 things:
1 - He assigned the bullet_point to the barrel of his guns, i really don’t think it makes any difference, but maybe i’ve done something wrong when positioning this node?

2 - As you can see below, this is the way he arranges things, which is different than mine, as the main difference is he uses a camera only for fps, but i use two cameras, one for rendering the world, and one only for rendering the guns (this being the view_model_cam)

Your code worked for me after I made the camera changes and made sure it wasn’t using the subviewport world3d.

I’ll make a pull request so you can see my changes.

I spent a couple hours digging through your code and I kept running into secondary code structure issues. I think your code is overdue for a major refactor.

I think the visual representation of the guns via a subviewport is fine, but you need to get the weapons_manager, hitscan, and bullet_point stuff out from under the subviewport.

My time is finite, sorry i couldn’t come up with a solution.

Ok, i think what you’re trying yo say is, that weapons_manager and all that needs to be a separate place? Well, i don’t know how i could do that and maintain it a son of view_model_cam aswell, but hey, you already helped me enough bro, thanks alot really!

1 Like

I was curious to how others did it and there is another option, a perspective shader.

If you went this way you wouldn’t have to work around viewport shenanigans.

Ohhh definitely gonna be checking that. If that really works, i can safely disclose all the subviewport stuff and things might get running again. Thanks again, highly appreciate all the help