apply_central_impulse direction

Godot Version

4.2.2

Question

OK, new… I mean NEW with Godot.

Question is about impulse force and trying to get a force acted on a RidgidBody3D so that NO matter where the collision, the force is applied to the object in the direction of the projectile the script here is attached to. So if the player hits this thing at the edge… still I want that body to pushed in the exact direction the projectile is traveling. While central hits behave as you think… the edge hits are like playing pool, which isn’t the desired effect.

It’s first learning project, so tread lightly
GitHub

YouTube video of what it’s doing

extends RigidBody3D

@onready var raycast = $RayCast3D
@export var explosion_scene: PackedScene
@export var offset_distance: float = -0.25
@export var sound: AudioStream
@export var impulse_strength: float = 10.0

func _ready():
	connect("body_entered", Callable(self, "_on_body_entered"))

func _on_body_entered(body: Node):
	if body != self:
		raycast.enabled = true
		
		if raycast.is_colliding():
			var trajectory_direction = -linear_velocity.normalized()
			
			if body is RigidBody3D:
				var impulse = trajectory_direction * impulse_strength
				body.apply_central_impulse(impulse)
				body.angular_velocity = Vector3.ZERO

			if explosion_scene:
				var explosion_instance = explosion_scene.instantiate()
				if get_parent():
					get_parent().add_child(explosion_instance)
					explosion_instance.global_transform.origin = global_transform.origin - trajectory_direction * offset_distance
					explosion_instance.look_at(global_transform.origin + trajectory_direction, Vector3.UP)

			var audio_player = AudioStreamPlayer3D.new()
			audio_player.stream = sound
			get_parent().add_child(audio_player)
			audio_player.global_transform.origin = global_transform.origin
			audio_player.play(0)

		queue_free()

Critique.

Banging my head against the wall…

the point to point direction wasn’t the fix totally… I’ll end up getting the direction in the same place I get the initial point (After we set the projectile on its way)

What I think was happening… we were reaching into the projectiles direction or velocity before the shooter script could send it on its way. Or at least it was the problem during or after versions in original post to this one. Either way, works as intended now

Why this way? Yea I get it… but later in a networked game… this simplifies how a game could be played especially when collisions are viewed by different players.

extends RigidBody3D

@onready var raycast = $RayCast3D
@export var explosion_scene: PackedScene
@export var sound: AudioStream
@export var impulse_strength: float = 10.0

var initial_position: Vector3
var has_started_moving: bool = false

func _ready():
	connect("body_entered", Callable(self, "_on_body_entered"))

func _physics_process(delta: float):
	if not has_started_moving and linear_velocity.length_squared() > 0.01:
		initial_position = global_transform.origin
		has_started_moving = true

func _on_body_entered(body: Node):
	if body != self:
		raycast.enabled = true
		if raycast.is_colliding():
			_apply_impulse(body)
			_create_explosion()
			_play_sound()
		queue_free()


func _apply_impulse(body: Node):
	if body is RigidBody3D:
		var force_direction = initial_position.direction_to(global_transform.origin)
		var impulse = force_direction * impulse_strength
		body.apply_central_impulse(impulse)
		body.angular_velocity = Vector3.ZERO


func _create_explosion():
	if explosion_scene:
		var explosion_instance = explosion_scene.instantiate()
		if get_parent():
			get_parent().add_child(explosion_instance)
			explosion_instance.global_transform.origin = global_transform.origin


func _play_sound():
	var audio_player = AudioStreamPlayer3D.new()
	audio_player.stream = sound
	get_parent().add_child(audio_player)
	audio_player.global_transform.origin = global_transform.origin
	audio_player.play(0)