Turret

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class_name Turret
extends Spatial

export var body_rotation_limit := 90
export var head_rotation_limit := 30
export var body_speed := 0.8
export var head_speed := 1.0

onready var body = $Body
onready var head = $Body/Spatial/Head


func target(delta: float, global_position: Vector3):
	_rotate_body_towards(delta, global_position)
	_rotate_head_towards(delta, global_position)


func _rotate_body_towards(delta: float, global_position: Vector3) -> void:
	var relative_position: Vector3 = body.global_transform.xform_inv(global_position)
	relative_position.y = 0
	var angle_to_position := Vector3.FORWARD.signed_angle_to(relative_position, Vector3.UP)
	var angle_change := move_toward(0, angle_to_position, body_speed * delta)
	body.rotate_y(angle_change)
	body.rotation_degrees.y = clamp(
		body.rotation_degrees.y, -body_rotation_limit, body_rotation_limit
	)


func _rotate_head_towards(delta: float, global_position: Vector3) -> void:
	var relative_position: Vector3 = head.global_transform.xform_inv(global_position)
	relative_position.x = 0
	var angle_to_position := Vector3.FORWARD.signed_angle_to(relative_position, Vector3.RIGHT)
	var angle_change := move_toward(0, angle_to_position, head_speed * delta)
	head.rotate_x(angle_change)
	head.rotation_degrees.x = clamp(
		head.rotation_degrees.x, -head_rotation_limit, head_rotation_limit
	)
turret.gd — Raw source code

From here, you can change things to better fit your needs. For example, you could make the rotation limits non-symmetric (e.g. the turret could aim higher than lower), but that’s left as an exercise for the reader :)

Thanks to Why485 for making GunTurrets2.