Look at target

Eight cones running look_at on the same moving orb. One call per frame replaces all the trigonometry.

The editor above is running this project. Change a line and it reloads.

Godot classes used

Node3DMeshInstance3DOmniLight3D

The code

scripts/main.gd
extends Node

const POINTERS: int = 8
const RING: float = 6.0
const ROAM: float = 2.2

var pointers: Array[Node3D] = []
var target: Node3D
var elapsed: float = 0.0


func _ready() -> void:
	_add_environment()
	_add_light()
	_add_ground()

	for i in POINTERS:
		var turn: float = TAU * i / POINTERS
		pointers.append(_add_pointer(Vector3(cos(turn), 0, sin(turn)) * RING + Vector3(0, 1.1, 0), float(i) / POINTERS))

	target = _add_target()

	var camera: Camera3D = Camera3D.new()
	camera.position = Vector3(0, 6.0, 11.5)
	add_child(camera)
	camera.look_at(Vector3(0, 2.0, 0), Vector3.UP)
	camera.current = true

	_aim()

	print('every cone runs look_at on the yellow orb, so all eight track it at once')


func _process(delta: float) -> void:
	elapsed += delta

	# the orb stays inside the ring, so it never lines up with a cone and makes look_at singular
	target.position = Vector3(
		sin(elapsed * 0.8) * ROAM,
		2.2 + sin(elapsed * 1.3) * 0.7,
		cos(elapsed * 0.5) * ROAM
	)

	_aim()


func _aim() -> void:
	for pointer in pointers:
		pointer.look_at(target.position, Vector3.UP)


func _add_pointer(at: Vector3, hue: float) -> Node3D:
	var cone: CylinderMesh = CylinderMesh.new()
	cone.top_radius = 0.0
	cone.bottom_radius = 0.5
	cone.height = 1.8
	cone.radial_segments = 12

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color.from_hsv(hue, 0.5, 0.95)
	material.roughness = 0.45

	# look_at aims the local -Z, and a cone from CylinderMesh grows along +Y
	var visual: MeshInstance3D = MeshInstance3D.new()
	visual.mesh = cone
	visual.material_override = material
	visual.rotation_degrees = Vector3(-90, 0, 0)

	var base: CylinderMesh = CylinderMesh.new()
	base.top_radius = 0.55
	base.bottom_radius = 0.55
	base.height = 0.25

	var stand: MeshInstance3D = MeshInstance3D.new()
	stand.mesh = base
	stand.material_override = _make_material('#2a2f3d', 0.7)

	var pointer: Node3D = Node3D.new()
	pointer.position = at
	pointer.add_child(visual)
	add_child(pointer)

	stand.position = Vector3(at.x, 0.12, at.z)
	add_child(stand)

	return pointer


func _add_target() -> Node3D:
	var mesh: SphereMesh = SphereMesh.new()
	mesh.radius = 0.75
	mesh.height = 1.5

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color('#f3d48d')
	material.emission_enabled = true
	material.emission = Color('#f3d48d')
	material.emission_energy_multiplier = 1.0

	var orb: MeshInstance3D = MeshInstance3D.new()
	orb.mesh = mesh
	orb.material_override = material
	orb.position = Vector3(0, 2.4, ROAM)
	add_child(orb)

	var glow: OmniLight3D = OmniLight3D.new()
	glow.light_color = Color('#f3d48d')
	glow.light_energy = 2.2
	glow.omni_range = 14.0
	orb.add_child(glow)

	return orb


func _add_ground() -> void:
	var mesh: PlaneMesh = PlaneMesh.new()
	mesh.size = Vector2(300, 300)

	var ground: MeshInstance3D = MeshInstance3D.new()
	ground.mesh = mesh
	ground.material_override = _make_material('#242938', 0.95)
	add_child(ground)


func _make_material(hex: String, roughness: float) -> StandardMaterial3D:
	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color(hex)
	material.roughness = roughness

	return material


func _add_environment() -> void:
	var sky_material: ProceduralSkyMaterial = ProceduralSkyMaterial.new()
	sky_material.sky_top_color = Color(0.07, 0.09, 0.18)
	sky_material.sky_horizon_color = Color(0.26, 0.29, 0.4)
	sky_material.ground_bottom_color = Color(0.05, 0.06, 0.09)
	sky_material.ground_horizon_color = Color(0.18, 0.2, 0.28)

	var sky: Sky = Sky.new()
	sky.sky_material = sky_material

	var env: Environment = Environment.new()
	env.background_mode = Environment.BG_SKY
	env.sky = sky
	env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
	env.ambient_light_energy = 0.75

	var world: WorldEnvironment = WorldEnvironment.new()
	world.environment = env
	add_child(world)


func _add_light() -> void:
	var light: DirectionalLight3D = DirectionalLight3D.new()
	light.rotation_degrees = Vector3(-58, -35, 0)
	light.light_energy = 1.1
	add_child(light)

More 3D scene examples