Hey there I need to implement a menu character selection, and choose charaters to play with.
In the CharacterSelection class, the logic for the character selection menu is implemented before the game begins. Therefore, it is important that player data and chosen character data are stored correctly in the CharacterSelection class before moving on to the next scene, where the corresponding player prefabs for the chosen characters are created.
When human players choose their characters, they must be assigned to a corresponding player so that the prefabs for the chosen characters can be created in the next scene of the game. It is important that this information is stored correctly in the CharacterSelection class so that it can be used as data for the selected characters in an object that can be accessed from the next scene. Then, in the next scene, this data can be used to create the corresponding player prefabs.
this is the CHaracter’s menu selection (not players by it self, just selecting , this scene works OK in terms of slecciont and confirm.
However I can not instantiate the “Prefab” of the selected character to the Player’s selection…
I got this script to control this logic.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using System;
public class CharacterSelection : MonoBehaviour
{
public Image[] characterImages;
public Image[] selectedCharacterImages;
public CharacterData[] characterData;
public Sprite[] selectedCharacters;
public int maxPlayers = 4;
private int selectedPlayerIndex = -1;
private int[] selectedPlayerIndices;
int currentSelectedIndex = 0;
private int selectedPlayers = 0;
public bool[] playersReady;
public GameManager gameManager;
[SerializeField] private bool gameStarted = false;
private Vector2 moveInput;
public CreditsCoins creditsCoins;
public int SelectedPlayerIndex { get => selectedPlayerIndex; set => selectedPlayerIndex = value; }
private PlaceHoldersCharactersInstances[] placeHolderInstances;
public static event Action OnLoadScene;
public static event Action OnMenuSelectionCharacter;
public static event Action OnSoundAcceptedCharacter;
void Start()
{
selectedPlayerIndices = new int[maxPlayers];
for (int i = 0; i < maxPlayers; i++)
{
selectedPlayerIndices[i] = -1; //
}
playersReady = new bool[maxPlayers];
foreach (Image characterImage in characterImages)
{
characterImage.gameObject.SetActive(true);
}
foreach (bool playerReady in playersReady)
{
Debug.LogFormat("Player is ready : {0} ", playerReady); //
}
}
private void StartTheGame()
{
if (!gameStarted && selectedPlayers > 0)
{
bool allReady = true;
for (int i = 0; i < selectedPlayers; i++)
{
if (!playersReady[i])
{
allReady = false;
break;
}
}
if (allReady)
{
gameStarted = true;
OnLoadScene?.Invoke();
}
}
}
void SelectPlayer(int playerIndex)
{
if (selectedPlayers < maxPlayers)
{
Debug.LogWarning("***SELECTING ****");
playersReady[playerIndex] = true;
selectedCharacterImages[selectedPlayers].sprite = selectedCharacters[playerIndex];
selectedCharacterImages[selectedPlayers].gameObject.SetActive(true);
selectedPlayers++;
selectedPlayerIndices[selectedPlayers - 1] = playerIndex;
SelectedPlayerIndex = playerIndex;
}
else if (SelectedPlayerIndex != playerIndex)
{
SelectedPlayerIndex = playerIndex;
}
else
{
selectedPlayerIndices[currentSelectedIndex] = playerIndex;
}
currentSelectedIndex = SelectedPlayerIndex;
selectedCharacterImages[currentSelectedIndex].sprite = selectedCharacters[SelectedPlayerIndex];
selectedCharacterImages[currentSelectedIndex].gameObject.SetActive(true);
selectedCharacterImages[(currentSelectedIndex + maxPlayers - 1) % maxPlayers].gameObject.SetActive(false);
string selectedCharacterName = characterData[SelectedPlayerIndex].characterName;
Debug.Log("Selected character: " + selectedCharacterName);
int readyPlayers = 0;
for (int i = 0; i < maxPlayers; i++)
{
if (playersReady[i])
{
readyPlayers++;
}
}
if (readyPlayers == maxPlayers)
{
OnLoadScene?.Invoke();
}
}
public void OnSelectionCharacter(InputAction.CallbackContext selection)
{
moveInput = selection.ReadValue<Vector2>();
if (moveInput.x > 0 && selection.performed)
{
SelectedPlayerIndex++;
SelectedPlayerIndex = Mathf.Clamp(SelectedPlayerIndex, 0, maxPlayers - 1);
selectedCharacterImages[currentSelectedIndex].gameObject.SetActive(false);
SelectPlayer(SelectedPlayerIndex);
OnMenuSelectionCharacter?.Invoke();
}
else if (moveInput.x < 0 && selection.performed && SelectedPlayerIndex != 0)
{
SelectedPlayerIndex--;
SelectedPlayerIndex = Mathf.Clamp(SelectedPlayerIndex, 0, maxPlayers - 1);
selectedCharacterImages[currentSelectedIndex].gameObject.SetActive(false);
SelectPlayer(SelectedPlayerIndex);
OnMenuSelectionCharacter?.Invoke();
}
int selectedCharacterIndex = selectedPlayerIndices[SelectedPlayerIndex];
string selectedCharacterName = characterData[selectedCharacterIndex].characterName;
Debug.Log("Selected character index: " + selectedCharacterIndex);
Debug.Log("Selected character name: " + selectedCharacterName);
}
public void OnConfirm(InputAction.CallbackContext accept)
{
if (accept.performed)
{
Debug.Log("Accepted");
OnSoundAcceptedCharacter?.Invoke();
AcceptedCharacter();
}
}
public void AcceptedCharacter()
{
int selectedCharacterIndex = selectedPlayerIndices[SelectedPlayerIndex];
GameObject placeHoldersObject = GameObject.Find("PlaceHoldersObject");
if (placeHoldersObject != null)
{
PlaceHoldersCharactersInstances placeHolders = placeHoldersObject.GetComponent<PlaceHoldersCharactersInstances>();
if (placeHolders != null)
{
placeHolders.SetSelectedCharacter(selectedCharacterIndex);
}
}
}
public void CountActivePlayers()
{
int activePlayers = 0;
string activePlayersText = "";
List<PlayerReadyData> readyPlayers = creditsCoins.GetReadyPlayers();
foreach (PlayerReadyData playerData in readyPlayers)
{
if (playerData.isReady)
{
activePlayers++;
activePlayersText += "P" + (playerData.playerNumber + 1) + ", ";
}
else
{
activePlayersText += "(No Listo), ";
}
}
Debug.LogFormat("Número of players active: {0}", activePlayers);
Debug.LogFormat("players actives: {0}", activePlayersText);
}
}
then I got 2 scriptable objects (one for players ready only ) and other for characterData (name,id,index,portrait,etc)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Character Data", menuName = "Character Data")]
public class CharacterData : ScriptableObject
{
public Sprite portrait;
public string characterName;
public int characterIndex; // Índice del personaje
public enum CharacterType
{
Gen,
Burn,
Khan,
Jack
}
}
and the other scriptable objects when Player or players are ready …
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
[CreateAssetMenu(fileName = "PlayerReadyData", menuName = "Player Ready Data")]
public class PlayerReadyData : ScriptableObject
{
public int playerNumber;
public bool isReady;
public int creditCount; // Crédito individual del jugador
public CharacterData selectedCharacter; // Personaje seleccionado
internal InputDevice inputDevice; //que input usa
}
