Got it working on Terrain3D..Path3d height automatic on terrain3d

A new version because it was not fully working yet, this one is stable:

@tool
extends Path3D

@export var fence_scene1 = preload("res://fence.tscn")
@export var fence_scene2 = preload("res://fence2.tscn")
@export var terrain: Node3D
@export var spacing = 0.3:
	set(value):
		spacing = value
		if Engine.is_editor_hint() and is_inside_tree():
			spawn_fences()  # 🔁 Herbouw hekjes bij wijziging in editor

@export var height_offset = 0.0:  # Zet standaard hoogte offset op 0 (geen zweven)
	set(value):
		height_offset = value
		if Engine.is_editor_hint() and is_inside_tree():
			spawn_fences()  # 🔁 Herbouw hekjes bij wijziging in editor

@export var enable_random_rotation := true:
	set(value):
		enable_random_rotation = value
		if Engine.is_editor_hint() and is_inside_tree():
			spawn_fences()  # 🔁 Herbouw hekjes bij wijziging in editor

var is_updating = false

func _ready():
	if !$VisibleItems3:
		var visible_items = Node3D.new()
		visible_items.name = "VisibleItems3"
		add_child(visible_items)

	curve.connect("changed", Callable(self, "_on_curve_changed"))

	adjust_curve_with_terrain_data()
	spawn_fences()

func _on_curve_changed():
	if is_updating:
		return
	is_updating = true

	adjust_curve_with_terrain_data()
	spawn_fences()

	is_updating = false

func adjust_curve_with_terrain_data():
	if terrain == null or terrain.data == null:
		push_error("❌ Geen geldig Terrain3D gekoppeld!")
		return

	if curve.point_count == 0:
		push_error("❌ Path3D heeft geen punten! Voeg punten toe.")
		return

	print("🔎 Path3D heeft", curve.point_count, "punten. Start hoogte-aanpassing...")

	for i in range(curve.point_count):
		var point = curve.get_point_position(i)
		var terrain_height = get_terrain_height(point)

		if !is_nan(terrain_height) and !is_inf(terrain_height):
			var new_point = Vector3(point.x, terrain_height + height_offset, point.z)
			curve.set_point_position(i, new_point)
			print("✅ Punt aangepast:", new_point)
		else:
			push_error("⚠️ Ongeldige hoogte voor punt " + str(point) + ", behoud originele hoogte.")

func get_terrain_height(global_position: Vector3) -> float:
	print("🌍 Controleren Terrain3DRegion voor positie:", global_position)

	if terrain == null or terrain.data == null:
		push_error("❌ Geen geldig Terrain3D gekoppeld!")
		return global_position.y  # Als er geen terrein is, behoud de oorspronkelijke hoogte

	global_position = to_global(global_position)
	print("🔎 Global position na conversie:", global_position)

	var height: float = terrain.data.get_height(global_position) * terrain.scale.y
	print("✅ Ontvangen hoogte:", height)

	if is_nan(height) or is_inf(height):
		push_error("⚠️ Ongeldige hoogte ontvangen voor " + str(global_position) + ", val terug op 0.")
		return 0.0

	return height

func spawn_fences():
	if terrain == null:
		push_error("❌ Geen geldig Terrain3D gekoppeld!")
		return

	for child in $VisibleItems3.get_children():
		child.queue_free()

	var current_distance = 0.0

	while current_distance < curve.get_baked_length():
		var pos = curve.sample_baked(current_distance)
		var next_pos = curve.sample_baked(current_distance + 0.1)

		pos = to_global(pos)
		next_pos = to_global(next_pos)

		var terrain_height = get_terrain_height(pos)
		if !is_nan(terrain_height) and !is_inf(terrain_height):
			pos.y = terrain_height + height_offset  # Pas de hoogte van het hek aan op de terrain hoogte

		var direction = (next_pos - pos).normalized()
		direction.y = 0

		var fence_instance = (fence_scene1 if randf() < 0.5 else fence_scene2).instantiate()

		if direction.length() > 0:
			var basis = Basis().looking_at(direction, Vector3.UP)
			var transform = Transform3D(basis, pos)
			fence_instance.transform = transform
		else:
			fence_instance.position = pos

		$VisibleItems3.add_child(fence_instance)

		if enable_random_rotation:
			fence_instance.rotate_y(randf_range(0.0, 2.0 * PI))

		current_distance += spacing

func randf_range(min_val: float, max_val: float) -> float:
	return min_val + (max_val - min_val) * randf()