Character Selection UI/screen

Godot Version

4.4

would someone Help me make 2player selection screen for only 2 Characters available?
i have been struggling for a month and im still a rookie in coding :confused:

You’ve made a similar topic before, it’s better to reply to that one with more information if nobody has responded. There is no way to help you without significantly more information. The bare minimum to explain is what you’ve tried and how it failed, specifically what you expect to happen versus what really happens. Character selection varies from game to game so posting any sort of reference would clarify what you mean.

Are you working on a local multiplayer game or networked? Which part of this project are you specifically struggling with, making the UI visuals, implementing the controls, managing who controls which objects?

Local coop and networked , struggling with implementing controlls and managing which one controls which character

Can you share a screenshot of your UI then? What code do you have so far?


heres Ui
i watched tutorial called
How to character selection for 2 players - Learn Godot 4 UI - no talking but its kinda not exactly what i wanted to learn anyway heres code

#character Selection's Script
extends Control

@onready var p_1_selection = %P1Selection
@onready var grid_container = %GridContainer
@onready var p_2_selection = %P2Selection


var player1SelectionIndex: int = 1
var player2SelectionIndex: int = 2

var player1Character: Character_Resource_Birds
var player2Character: Character_Resource_Birds



func _ready() -> void:
	_refresh_selection()
	

func _refresh_selection():
	for child in grid_container.get_children():
		child.reset()

	var startContainerP1 = grid_container.get_child(player1SelectionIndex)
	var startContainerP2 = grid_container.get_child(player2SelectionIndex)
	
	startContainerP1.set_player_selection(CharacterSelectionBox.Player.PLAYER1)
	p_1_selection.texture = startContainerP1.get_character().texture
	
	startContainerP2.set_player_selection(CharacterSelectionBox.Player.PLAYER2)
	p_2_selection.texture = startContainerP2.get_character().texture
	
	
func _input(event: InputEvent) -> void:
	if not event.is_pressed(): return
	var player1Direction = Input.get_axis("P1_Move Left", "P1_Move Right")
	var player2Direction = Input.get_axis("P2_Move Left", "P2_Move Right")
	
	if not player1Character:
		player1SelectionIndex = _get_selection_index(player1SelectionIndex, player1Direction)
	if not player1Character:
		player2SelectionIndex = _get_selection_index(player2SelectionIndex, player2Direction)
	
	_refresh_selection()

	if Input.is_action_just_pressed("P1_Interact"):
		player1Character = grid_container.get_child(player1SelectionIndex).get_character()
	if Input.is_action_just_pressed("P2_Interact"):
		player2Character = grid_container.get_child(player2SelectionIndex).get_character()
		
	_check_selection_done()



func _get_selection_index(currentIndex: int, direction:Vector2i):
	var index: int = currentIndex
	
	if direction.x:
		index = currentIndex + direction.x
	
	var selectedContainer = grid_container.get_child(index)
	if selectedContainer and selectedContainer.selectable and not selectedContainer.selected:
		return index
	else:
		return currentIndex


func _check_selection_done():
	if player1Character and player2SelectionIndex:
		pass


Selection frame's script
extends Control
class_name  CharacterSelectionBox

@export var  selectable = true 
@export var character: Character_Resource_Birds

@onready  var p_1_texture: TextureRect = $TextureRect
@onready  var p_2_texture: TextureRect = $TextureRect2

enum Player {NONE, PLAYER1, PLAYER2}
var selected = false

func _ready() -> void:
	p_1_texture.hide()
	p_2_texture.hide()

func set_player_selection(player:Player):
	
	if player == Player.PLAYER1:
		selected = true 
		p_1_texture.show()
	elif player == Player.PLAYER2:
		selected = true 
		p_2_texture.show()

func get_character():
	return character

func reset():
	selected = false 
	
	p_1_texture.hide()
	p_2_texture.hide()


Nice, and how does this script fail you? What do you expect to happen versus what really happens?

havent tried it because yet set_player_selection is a null instance, cant find the wrong spelling or whatever it is yet

set_player_selection probably isn’t null, I’m guessing your error is along the lines of “called set_player_selection on nil” which means what ever you are calling set_player_selection on is null, so what ever is left of the . in help_i_am_nil.set_player_selection(0).

Please post your full error, and if you can mark which line causes the error such as by quoting your last post where it happens, I’m guessing it’s one of these lines triggering the error

Attempt to call function ‘set_player_selection’ in base ‘null instance’ on a null instance.

Awesome, and from that screenshot we can see that in the debugger “Locals” lists startContainerP1 as a valid object while startContainerP2 is null.

It’s probably because your grid_container only has two children, but your player2SelectionIndex is 2, and indexes start at zero, try changing these lines to better match how indexes start at zero

into:

var player1SelectionIndex: int = 0
var player2SelectionIndex: int = 1

That should at least fix that error.

ye it did now what should i use instead of Vector2i to only X axis, heres error
Invalid type in function ‘_get_selection_index’ in base ‘Control (character_selection.gd)’. Cannot convert argument 2 from float to Vector2i.

Your _get_selection_index expects a Vector2i (X and Y) but you are giving it a player1Direction which is only X. I’d recommend changing _get_selection_index to take a int, for just the X axis.

func _get_selection_index(currentIndex: int, direction: int): # int is one value
	var index: int = currentIndex
	
	if direction: # removed .x
		index = currentIndex + direction # removed .x

alright now code works well here’s what i want to happen, this code allow only 1 selection box
so Player 2’s selectionbox cant get to player1’s character Texutre, what i want is allow players’s selectionbox to be able to stand on same Character, and Change Selection Box Texture to this


until one of them leave character area, and change Controls depending on what each player selected, should i send Players’s code?

That may be a complicated change from the script posted. Currently your boxes only track if they are selected

You may need to track who is selecting them, and luckily you have the enum Player just above that may be of some use.

enum Player {NONE, PLAYER1, PLAYER2, BOTH} # added BOTH
var selected: Player = Player.NONE # changed to Player type

Now first this selection box script needs some updating with set_player_selection and reset

func reset():
	selected = Player.NONE # using the Player type instead of false
	# ...


func set_player_selection(player:Player):
	if selected == Player.NONE: # check the current selection
		selected = player
	elif selected != player: # check if setting the other player
		selected = Player.BOTH

	# update texture based on selected
	if selected == Player.PLAYER1:
		p_1_texture.show()
	elif selected == Player.PLAYER2:
		p_2_texture.show()
	elif selected == Player.BOTH:
		p_both_texture.show() # p_both_texture does not exist yet, you must create it

Then your main UI selection script needs a minor update, this line prevented the other selection from being selected

So you may only need to remove the last condition “not selectedContainer.selected

if selectedContainer and selectedContainer.selectable:
	return index

I’m not sure this will fix everything, but keep at it!

1 Like

nvm i figured it out

now i know how to send to other scene when both player select but idk how to make Player Control Set on character Depending on which player choice