Godot Version
4.6.2
Question
I have various attack types and one of them is field_attack — spawning a field upon firing. Where is the best place to keep the field scene itself? (Clearly not as a constant like it is now.)
class_name AttackTypeHandler extends Node
func apply_attack(
attack_types : Array[AttackType],
damage : float,
camera : Camera3D,
target : Node3D,
hit_point : Vector3,
normal : Vector3,
enemy_group : String = "enemies"
) -> void:
func _apply_direct_attack(damage : float, target : Node3D, hit_point : Vector3, normal : Vector3) -> void:
func _apply_splash_attack(
damage : float,
camera : Camera3D,
splash_radius : float,
hit_point : Vector3,
normal : Vector3,
enemy_group : String
) -> void:
const FIELD_SCENE: PackedScene = preload("res://scenes/entity/field/Field.tscn")
func _apply_field_attack(
damage : float,
camera : Camera3D,
field_radius : float,
field_duration : float,
hit_point : Vector3,
normal : Vector3,
enemy_group : String
) -> void:
func _apply_damage_to_target(damage : float, target : Node3D) -> void:
What’s wrong with keeping it in the constant?
If you want to change a lot for different enemies, make it an @export variable.
So It’s not a bad practice? That scene is just for technical reasons, wouldn’t change somehow
If you always are going to use it, or at least plan to use it more than 50% of the time, then no it’s not a bad practice. Otherwise you can turn it into a load statement and load it in the function when you need it. (But that could lag the game.)
One small thing. Move the const to the top of your file.
also, in reading your code, you are passing a LOT of arguments. If they’re all necessary, think about creating a Resource that can hold references to all those values and pass it instead. It’ll make your code a lot easier to read.
class_name AttackTypeHandler extends Node
const FIELD_SCENE: PackedScene = preload("res://scenes/entity/field/Field.tscn")
func apply_attack(
attack_types : Array[AttackType],
damage : float,
camera : Camera3D,
target : Node3D,
hit_point : Vector3,
normal : Vector3,
enemy_group : String = "enemies"
) -> void:
func _apply_direct_attack(damage : float, target : Node3D, hit_point : Vector3, normal : Vector3) -> void:
func _apply_splash_attack(
damage : float,
camera : Camera3D,
splash_radius : float,
hit_point : Vector3,
normal : Vector3,
enemy_group : String
) -> void:
func _apply_field_attack(
damage : float,
camera : Camera3D,
field_radius : float,
field_duration : float,
hit_point : Vector3,
normal : Vector3,
enemy_group : String
) -> void:
func _apply_damage_to_target(damage : float, target : Node3D) -> void:
Thx, I will try to use Resource, because all of those arguments are used in functions rn
class_name AttackDetails extends Resource
@export var attack_types: Array[AttackType]
@export var damage: float
@export var camera: Camera3D
@export var target : Node3D
@export var hit_point : Vector3
@export var normal : Vector3
@export var enemy_group : String = "enemies"
Then:
class_name AttackTypeHandler extends Node
const FIELD_SCENE: PackedScene = preload("res://scenes/entity/field/Field.tscn")
func apply_attack(attack_details: AttackDetails) -> void:
func _apply_direct_attack(damage : float, target : Node3D, hit_point : Vector3, normal : Vector3) -> void:
func _apply_splash_attack(attack_details: AttackDetails) -> void:
func _apply_field_attack(attack_details: AttackDetails) -> void:
func _apply_damage_to_target(damage : float, target : Node3D) -> void: