What would be the best way to implement a skin system?

Godot Version

Godot 4.3

Question

My objective would be to create a skin system, I’d obviously have to create a skin selection menu and that’s not a problem, what would be the best practice to make it code-wise though?

Do I just make a bunch of sprites and various booleans that make it so that a skin is instantiated in the level when selected? If so, how could I make it so that making a boolean true (I’d make it probably through the press of a button) sets all the other skin booleans false? Do I just program the similarly to each turn off every other skin’s boolean? It would work but at long time it would be hard to add a new line of code on each skin (more skins I add the more booleans I have to add and call on the other skin’s booleans)

Depends on how you want your skin selection menu to look like, because there are multiple ways of how you can achieve that.
Ideally, you’d want to store the “selected skin” value within just one variable, not multiple booleans.
E.g. You can have all the skins stored in the Array, where you can easily reference them by index. You can change the index by buttons “next” and “previous” and update the display to show the skin from that index. If you want to add another skin to the mix - just add it to the array and that’s it.
Here’s my quick and dirty demo, where I’m selecting colors, but in your case these could be sprites, textures, whatever.


Here’s my scene structure

And here’s the code

extends Control

@export var index_label: Label
@export var next_button: Button
@export var previous_button: Button
@export var color_display: ColorRect

@export var colors: Array[Color]

var current_index: int = 0


func _ready() -> void:
	next_button.pressed.connect(_on_next_button_pressed)
	previous_button.pressed.connect(_on_previous_button_pressed)
	update_display()


func _on_next_button_pressed() -> void:
	current_index = wrapi(current_index + 1, 0, colors.size())
	update_display()


func _on_previous_button_pressed() -> void:
	current_index = wrapi(current_index - 1, 0, colors.size())
	update_display()



func update_display() -> void:
	color_display.color = colors[current_index]
	index_label.text = str(current_index)

//EDIT: changed modulo operator with wrapi() function, because modulo loops to negative numbers, which is not desired for indexes.

1 Like

Thanks! I’ll learn how to properly use arrays and I’ll be able to do something similar, I never thought about that possibility.

1 Like