jerstopholes

Updated Camera Script

Jul 13th, 2025
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
GDScript 3.62 KB | Gaming | 0 0
  1. extends Node3D
  2.  
  3. # Variables to expose here
  4. ## Mouse Sensitivity
  5. @export var mouse_sensitivity : float = 100.0
  6. ## Minimum viewing angle (in degrees)
  7. @export_range(-90.0, 0.0, 0.1, "radians_as_degrees") var min_vertical_angle: float = -PI/2
  8. ## Maximum viewing angle (in degrees)
  9. @export_range(0.8, 90.0, 0.1, "radians_as_degrees") var max_vertical_angle: float = PI/4
  10.  
  11. ## The target the camera is to follow
  12. @export var follow_target : NodePath
  13.  
  14. # Onready vars here
  15. @onready var camera = %Camera3D
  16. @onready var marker = %Marker3D
  17. @onready var spring_arm = %SpringArm3D
  18. @onready var pivot = $"Pivot"
  19.  
  20. var can_clip : bool = false
  21. var clipping : bool = false
  22. var target : Node
  23. var target_pos : Vector3 = Vector3()
  24. var cam_offset : Vector3 = Vector3()
  25. var lerp_speed : float = 8.0
  26.  
  27. func _ready() -> void:
  28.     Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
  29.    
  30.     if follow_target:
  31.         target = get_node(follow_target)
  32.         spring_arm.add_excluded_object(target)
  33.         cam_offset = global_position - target.global_position
  34.        
  35.    
  36.     set_as_top_level(true)
  37.    
  38.     # Force physics interpolation OFF
  39.     set_physics_interpolation_mode(Node.PHYSICS_INTERPOLATION_MODE_OFF)
  40.    
  41.     # Force VSync on
  42.     DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
  43.    
  44. func _unhandled_input(event: InputEvent) -> void:
  45.     # Handle rotation of the camera here
  46.     if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
  47.         _rotate_camera(event)
  48.  
  49.     # Release/capture the mouse
  50.     if event.is_action_pressed("ui_cancel"):
  51.         if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
  52.             Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
  53.         else:
  54.             Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
  55.    
  56.     # Quick Quit (ALT + Q)
  57.     if event.is_action_pressed("quick_quit"):
  58.         get_tree().quit()
  59.  
  60. func _process(delta):
  61.     _follow_target(delta)
  62.     _rotate_camera(InputEvent)
  63.     _update_camera(delta)
  64.  
  65.        
  66. func _update_camera(delta):
  67.    
  68.     var marker_tf : Vector3 = marker.get_global_transform_interpolated().origin
  69.    
  70.     can_clip = spring_arm.get_hit_length() < spring_arm.spring_length
  71.    
  72.     if can_clip:
  73.         if camera.position.z > marker.position.z:
  74.             lerp_speed = 20.0
  75.         elif camera.position.z < marker.position.z:
  76.             lerp_speed = 8.0
  77.     else:
  78.         lerp_speed = 8.0
  79.  
  80.     camera.global_position = lerp(camera.global_position, marker_tf, lerp_speed * delta)
  81.  
  82.  
  83. func _follow_target(delta):
  84.    
  85.     var tf : Transform3D = target.get_global_transform_interpolated()
  86.    
  87.     var t_pos = tf.origin + cam_offset
  88.    
  89.     target_pos = lerp(target_pos, t_pos, 8.0 * delta)
  90.  
  91.     global_position = target_pos
  92.  
  93. func _rotate_camera(event) -> void:
  94.     if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
  95.         var viewport_transform: Transform2D = get_tree().root.get_final_transform()
  96.         var motion: Vector2 = event.xformed_by(viewport_transform).relative
  97.         var degrees_per_unit: float = 0.001
  98.        
  99.         motion *= mouse_sensitivity
  100.         motion *= degrees_per_unit
  101.        
  102.         # Don't apply rotation if we're not moving the mouse
  103.         if is_zero_approx(motion.length() > 0.01):
  104.             return
  105.  
  106.         # Apply pitch
  107.         pivot.rotate_object_local(Vector3.LEFT, deg_to_rad(motion.y))
  108.    
  109.         # Apply yaw
  110.         rotate_object_local(Vector3.DOWN, deg_to_rad(motion.x))
  111.        
  112.     if Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
  113.         var input_vector = Input.get_vector("look_right", "look_left", "look_down", "look_up")
  114.        
  115.         rotate_y(input_vector.x * 0.05)
  116.         pivot.rotate_x(input_vector.y * 0.05)
  117.        
  118.     # Clamp the rotation
  119.     pivot.rotation.x = clamp(pivot.rotation.x, min_vertical_angle, max_vertical_angle)
  120.     rotation.y = wrapf(rotation.y, 0.0, TAU)
  121.    
  122.     # Orthonormalize the transforms
  123.     pivot.orthonormalize()
  124.     orthonormalize()
Advertisement
Add Comment
Please, Sign In to add comment