class_name PerformanceComponent extends VisibleOnScreenNotifier3D const SKIP_FRAMES_INVISIBLE := 16 const SKIP_FRAMES_VISIBLE := 8 static var quality_budget: Array[int] = [ 10, # 0 skipped frames 10, # 1 skipped frame 10, # 2 skipped frames 10, # 3 skipped frames 10, # 4 skipped frames 10, # 5 skipped frames 10, # 6 skipped frames 10, # 7 skipped frames ] @export var animation: AnimationComponent var camera_distance_squared: float var on_screen: bool var skip_frames_visible: int func _ready(): assert(animation) screen_entered.connect(on_screen_entered) screen_exited.connect(on_screen_exited) func on_screen_entered(): on_screen = true animation.skip_frames = skip_frames_visible func on_screen_exited(): on_screen = false animation.skip_frames = SKIP_FRAMES_INVISIBLE static func update_all_animations(): var visible_players: Array[Player] = [] for player in Global.players.id_to_player.values(): player.performance.camera_distance_squared = player.global_position.distance_squared_to(Global.camera.global_position) if player.performance.on_screen: visible_players.append(player) else: player.performance.animation.skip_frames = SKIP_FRAMES_INVISIBLE if Global.player: Global.player.performance.camera_distance_squared = 0 visible_players.sort_custom(PerformanceComponent.distance_sort) var skip_frames := 0 var count := 0 for player in visible_players: if skip_frames >= quality_budget.size(): player.performance.skip_frames_visible = SKIP_FRAMES_VISIBLE player.animation.skip_frames = SKIP_FRAMES_VISIBLE continue player.performance.skip_frames_visible = skip_frames player.animation.skip_frames = skip_frames count += 1 if count >= quality_budget[skip_frames]: skip_frames += 1 count = 0 static func distance_sort(a: Player, b: Player) -> bool: return a.performance.camera_distance_squared < b.performance.camera_distance_squared