I created a script for Node2d in a 3D scene to draw a line with an arrow between two Sprite3ds, with the option to select a custom arrow as a texture.
extends Node2D
@export var line_thickness: float = 4.0
@export var arch_height: float = 80.0
@export var line_color: Color = Color.YELLOW
@export var sprite1: Node3D
@export var sprite2: Node3D
@export var camera: Camera3D
var arrow_length = 15.0
var arrow_angle_rad = deg_to_rad(35.0)
func _process(delta):
queue_redraw()
func _draw():
if not is_instance_valid(sprite1) or not is_instance_valid(sprite2) or not is_instance_valid(camera):
return
var pos1_3d = sprite1.global_position
var pos2_3d = sprite2.global_position
if camera.is_position_behind(pos1_3d) or camera.is_position_behind(pos2_3d):
return
var start_point = camera.unproject_position(pos1_3d)
var end_point = camera.unproject_position(pos2_3d)
var arch_direction = Vector2.UP
var midpoint = start_point.lerp(end_point, 0.5)
var control_point = midpoint + arch_direction * arch_height
var points = PackedVector2Array()
var num_segments = 30
for i in range(num_segments + 1):
var t = i / float(num_segments)
var point_on_curve = pow(1 - t, 2) * start_point + 2 * (1 - t) * t * control_point + pow(t, 2) * end_point
points.append(point_on_curve)
draw_polyline(points, line_color, line_thickness, true)
var t_peak = 0.5
var peak_point = pow(1 - t_peak, 2) * start_point + 2 * (1 - t_peak) * t_peak * control_point + pow(t_peak, 2) * end_point
var tangent = (end_point - start_point).normalized()
if tangent.is_zero_approx():
return
var dir_to_end = tangent
var dir_to_start = -tangent
var arrow1_p1 = peak_point + dir_to_start.rotated(arrow_angle_rad) * arrow_length
var arrow1_p2 = peak_point + dir_to_start.rotated(-arrow_angle_rad) * arrow_length
draw_line(peak_point, arrow1_p1, line_color, line_thickness, true)
draw_line(peak_point, arrow1_p2, line_color, line_thickness, true)
var arrow2_p1 = peak_point + dir_to_end.rotated(arrow_angle_rad) * arrow_length
var arrow2_p2 = peak_point + dir_to_end.rotated(-arrow_angle_rad) * arrow_length
draw_line(peak_point, arrow2_p1, line_color, line_thickness, true)
draw_line(peak_point, arrow2_p2, line_color, line_thickness, true)
As a final touch, I wanted to add a glowing effect to the arrowhead and the line itself, but I can’t figure out how to do it and don’t know what to do. I think shaders might be able to handle this, but I don’t understand them.