I am using these two functions for my Bullet scene right now:
func head_to(dest : Vector3, speed : float) -> void:
velocity = speed
var dv : Vector3 = dest - global_position
var d : float = sqrt( dv.x*dv.x + dv.y*dv.y + dv.z*dv.z )
velocity_vector.x = dv.x/d * velocity
velocity_vector.y = dv.y/d * velocity
velocity_vector.z = dv.z/d * velocity
look_at_from_position( global_position , dest )
func _physics_process(delta: float) -> void:
global_position += velocity_vector*delta
In this case, point A will be the global_position of the Bullet, and it will travel to point B (the parameter dest) at speed of parameter speed. We will calculate for the velocity_vector and apply delta in _physics_process. All of these are working validly already.
But I would like to add one more thing: deviation. I know point A and point B but the gun could have a bad deviation and when you shoot it, the bullet could have a randomized deviation angle of -5 to 5 degrees for every Bullet, for example. So how could this be accomplished mathematically?
NOTE: adding extra randomized x,y,z values on dest is NOT what I am looking for. I would like to be able to control the exact range of deviation angle of the bullet being shot.
How this works is that the initial shooting_direction vector (Vector3.FORWARD) is rotated horizontally within the ± max_angle_deviation restrictions around a random axis calculated with the random_rotation angle.
The rest of the code is just boiler plate code for the demo video.
You might still need to adjust it to fit your project, but maybe this will nudge you into the correct direction.
Thank you for this, but unfortunately, I am not using RigidBody3D for performance reasons. All of my bullets are Area3D, so apply_impulse does not exist in that class. This is why I am moving all those Bullets myself in _physics_process .
Do you appear to know the math for applying the deviation into the velocity_vector for above?
My code should be universally applicable regardless if you use RigidBody3D, or any other Node, just reuse this part to calculate the shooting_direction_with_deviation vector and apply it to your bullet.
var shooting_direction: Vector3 = Vector3.FORWARD
var max_angle_deviation: float = 5.0
func shoot() -> void:
var horizontal_angle_deviation = randf_range(-deg_to_rad(max_angle_deviation), deg_to_rad(max_angle_deviation))
var random_rotation = randf_range(0.0, TAU)
var shooting_direction_with_deviation = shooting_direction.rotated(Vector3.UP.rotated(Vector3.BACK, random_rotation), horizontal_angle_deviation).normalized()
In your code I think you can implement it as follow, but without knowing your full scene structure I’m not 100% sure this will work correctly. If there are any issues with this, let me know and we can try to debug.
A side note - using Area3D and changing the global_position directly might not be the best idea for managing bullets, because if your bullet is flying fast enough or your game lags for a second, it may miss the target by simply teleporting behind the target without registering collision.
I would still recommend you to use RigidBody3D, or CharacterBody3D, as these have tools that can ensure the collision is registered.
Your code on random deviation does indeed work. Thank you
Regarding the game lagging, I did consider that too. This is why I am using _physics_process function which runs every 16 ms instead of _process. I have tried spawning multiple bullets against a single target on both 1000 fps and 10 fps , and I see that for both cases, no bullets went through the target.
In fact, I used to ask this question before here: Can objects "go through" walls in a very low framerate? , and I already got my answer, but at the same time, while RigidBody is recommended for this case, this statement here from my link is a bit of a concern:
CastRay will use a raycast to detect passthorugh.
And Cast Shape will use a shapecast that is more precise, but much more expensive
I didn’t do a thorough measurement yet. (1000 RigidBody3D bullets VS 1000 Area3D bullets) But at this moment, I am thinking using Area3D with _physics_process above should be computationally less expensive than RigidBody3D. Or do you have an experience you would like to share?
But do you need this performance? In general, you shouldn’t try to optimize the game if you don’t need to.
I couldn’t argue with you if you said “rigidbodies lagged my game too much, so I decided to use areas instead”.
But here, if you decided to use areas without having issues with rigidbodies in the first place, I’d say this might have been a bad call. It’s because this decision while maybe having a slight improvement of performance (which you have not measured, and I would guess there is no visible difference in performance), it has its own additional drawbacks, which you need to take into consideration now.