Force_raycast_update failing on a highspeed object (3D)

Godot Version

v4.6.2

Question

I’m working on a game where the player can dodge which gives him a burst of speed. Additionally the enemies use raycasts to determine line of sight. However for whatever reason setting the player’s speed high results in the raycast not reporting a collision with the player when it should (this also happens if I just set the player’s speed to a high amount.) Additionally this only happens when calling force_raycast_update and not if I aim the raycast and check the result that is provided at the end of the frame, but I need force_raycast_update to work to utilize a sweep pattern.

My raycasts are positioned through setting the z target position to the distance between it and the player, then calling look_at(), force_update_transform() and finally the update. The raycasts work properly when the player is at a lower speed or if I set the Engine.time_scale value down. Furthermore this also applies to shapecasts and calling intersect_ray() in the space state didn’t work either. Are there any fixes for this?

Note that the highspeed object is a capsule with a radius of .35m and is moving at 25m/s, altough the same issue occurs at slightly slower speeds.

Here’s the code i used in a RayCast object to test both the node and calling intersect_ray():

func _physics_process(delta: float) -> void:
	
	var _targ = get_tree().get_first_node_in_group("player")
	
	var params = PhysicsRayQueryParameters3D.new()
	params.from = global_position
	params.to = _targ.global_position + (_targ.velocity * delta)
	
    #check using intersect ray
	var space_state = get_world_3d().direct_space_state
	var result = space_state.intersect_ray(params)
	print(result)
	if result.is_empty():
		print("EMPTY")
	
    #check with the raycast node itself
	var targdist = global_position.distance_to(_targ.global_position)
	target_position = Vector3.ZERO
	target_position.z = max(-100.0,-targdist)
	look_at(_targ.global_position + (_targ.velocity * delta))
	
	force_update_transform()
	force_raycast_update()
	
	if !is_colliding():
		print("NO COLLISION")

Why do you add (_targ.velocity * delta) here?

I was testing to see if I just needed to account for the player’s velocity for the casts to line up. It didn’t work and it doesn’t work without it either.

I ran some tests on a separate project and it looks like it works at certain angles but not at others (the closer they are to being colinear on the x or z axis seems to impact that) but I don’t know how I would fix that.

How far from the origin the things are?

Also, make sure you’re shooting the ray at the center of the capsule.

If you mean the raycast it’s it’s own separate object pointing directly at the origin of the player. If yuo’re talking about world space they are less than 20m from (0,0,0)

If you’d like I can post a minimum replication project here.

Let’s see it.

I actually do think I figured out the issue but not a solution; looks like when I grab the player’s global position after referencing it’s group it gives me one that’s behind the actual player position, so the raycast lags behind a bit. The offset it lags behind is smaller at low speeds which is why it still worked, but I don’t know how I could transfer the correct position to another object.

Try swapping the order of scripts in the scene tree.

Actually it turns out I had the print statements in the wrong order, so my idea was wrong and the raycast is reading the correct player global position but it still lags behind for some reason. I’m not sure what you mean by moving the order of the scripts; do you mean changing the order they are laid out from top to bottom? I tried shuffling them around but didn’t seem like anything was happening.

Arrange nodes in such a way that player movement script runs before raycasting script.

It is now, no change

In the MRP you posted you’re printing the target position before you call move_and_slide(). If you print it after the call, both printouts will be the same.

Right, I acknowledged that in a previous post

Well then MRP is not reproducing any problems.

Do you see the printout that prints the result of is_colliding()? If I run force_raycast_update(), the time_scale is at 1.0 and the target is moving at its full speed (25) it should result in the output printing false when it should return true. This issue does not occur if you comment out force_raycast_update and let is_colliding be the result of the automatic raycast update but I need it to work when I do call force_raycast_update. It also appears to be related to the angle the target is to the raycast as well as the movement direction of the target relative to the raycast but I can’t say in what manner.

If you scroll up the output log you should see more multiple false printed; I understand the first one occurs since it’s the first frame of action but aside from that it should always read true. Let me know if you still don’t see the problem and I’ll double check the MRP.

Use direct raycast query instead of a node.

I already tried that I stated that in the original post and it still doesn’t work.

If you move the raycast node to run before player movement code - no false printouts:

If you got it working on your end could you send the project back here? Thanks.

Edit: Nevermind, I got it to work. Thanks again. Is there a way I can set the order without having to worry the layout of the nodes in the tree? There are situations where I can see it being tedious and hard to manage (I may want enemies to raycast onto their comrades to check if a path to fire is clear, etc..)

I just dragged the raycast node above the target node. That’s all.