[RESOLU]La tyranie du clavier

Questions à propos du scripting. Hors Shader, GUI, Audio et Mobile.
Bilu
Messages : 91
Inscription : 20 Nov 2019 09:24

[RESOLU]La tyranie du clavier

Message par Bilu » 08 Sep 2023 09:48

Bonjour à tous,

Je travaille sur un jeu multijoueur local et je rencontre un problème avec les input et les contrôleurs du joueur.
J'ai deux scène :
1°) Les joueurs appuient sur un bouton de leur contrôleur (clavier+souris ou manette) pour apparaître à l'écran. Et ils choisissent une équipe avec laquelle jouer. Il y a 4 équipes parmi lesquelles choisir. Et lorsque tous les joueurs sont prêts, une deuxième scène est chargée.
2°) Les joueurs apparaissent à des positions différentes par rapport à leur équipe dans cette seconde scène.


Si le premier joueur est contrôlé par le clavier+souris et le second est contrôlé par une manette de jeu dans la première scène, après le chargement de la deuxième scène, le joueur 1 est toujours contrôlé par le clavier et le joueur 2 est toujours contrôlé par la manette de jeu.

Essayons maintenant si le clavier n'est PAS ce qui contrôle le joueur 1 :
a) Dans la première scène, si le joueur 1 est contrôlé par une manette de jeu et le deuxième joueur par le clavier, lorsque la deuxième scène est chargée, le premier joueur est désormais contrôlé par le clavier et le deuxième joueur est désormais contrôlé par la manette de jeu. .
Et dans le composant "Player Input", je peux effectivement voir que désormais le clavier contrôle le joueur 1 et le joystick contrôle le joueur 2. Alors que dans la scène de sélection d'équipe, c'était l'inverse.
Le joueurs 1 contrôle le personnage du joueur 2 et inversement

b) Si dans la première scène, le joueur 1 est contrôlé par une manette de jeu et le deuxième joueur est contrôlé par une deuxième manette de jeu. Une fois la deuxième scène chargée, le premier joueur peut être contrôlé par la première manette de jeu mais le deuxième joueur ne bouge pas du tout. Parce que dans son composant Player Input, je vois que le joueur 2 attend une saisie au clavier (mais comme aucun clavier n'a été utilisé dans la scène 1, si j'appuie sur mon clavier, le joueur 2 ne bouge pas. Il attend donc l'input d'un clavier inexistant ...

c) Si j'utilise le clavier pour le joueur 1, une première manette pour le joueur 2 et une deuxième manette pour le joueur 3, tout fonctionne très bien.

d) Si j'utilise une première manette pour le joueur 1, le clavier pour le joueur 2 et une deuxième manette pour le joueur 3, encore une fois le clavier reprend le contrôle du joueur 1 et la première manette permet de contrôler le joueur 2 mais la deuxième manette contrôle bien le joueur 3.

Je ne sais pas si c'est mon script qui a conduit à ce problème ou s'il y a quelque chose que je ne saisi pas bien dans le fonctionnement de Unity alors voici mes scripts :

PlayerConfigurationManager.cs est appelé à chaque fois qu'un joueur rejoint (en appuyant sur un bouton du contrôleur) dans la première scène (où les joueurs doivent choisir une équipe) et la fonction "HandlePlayerJoin" est utilisée.

Code : Tout sélectionner

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.InputSystem;
using System.Linq;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine;
 
public class PlayerConfigurationManager : MonoBehaviour
{
    private List<PlayerConfiguration> _playerConfigs;
 
    [SerializeField] private int _maxPlayer = 4;
    [SerializeField] private int _minPlayer = 2;
 
    [SerializeField] private TextMeshProUGUI _textNumberOfPlayer;
    [SerializeField] private TextMeshProUGUI _textNumberOfJoinedPlayer;
 
    public static PlayerConfigurationManager Instance { get; private set; }
 
 
    private void Awake()
    {
        if (Instance != null)
        {
            Debug.Log("SINGLETON : Trying to create another instance of singleton!");
        }
        else
        {
            Instance = this;
         
            _playerConfigs = new List<PlayerConfiguration>();
         
        }
    }
    public void SetPlayerColor (int index, Material color)
    {
        _playerConfigs[index].PlayerMaterial = color;
    }
 
    public void SetTeam(int index, int teamNumber)
    {
        _playerConfigs[index].Team = teamNumber;
    }
 
    public void ReadyPlayer(int index)
    {
        _playerConfigs[index].IsReady = true;
        if (_playerConfigs.Count >= _minPlayer && _playerConfigs.All(p => p.IsReady == true))
        {
            SceneManager.LoadScene("TopDownScene");
        }
    }
 
    public void UnreadyPlayer(int index)
    {
        _playerConfigs[index].IsReady = false;
    }
 
    public void HandlePlayerJoin(UnityEngine.InputSystem.PlayerInput pi)
    {
     
        if(!_playerConfigs.Any(p => p.PlayerIndex == pi.playerIndex))
        {
            pi.transform.SetParent(transform);
            _playerConfigs.Add( new PlayerConfiguration(pi));
         
            _textNumberOfPlayer.GetComponent<PlayerNumberReadyTextScript>().SetPlayerCount(_playerConfigs.Count);
            _textNumberOfJoinedPlayer.GetComponent<TextToJoinScript>().SetJoinedPlayerCount(_playerConfigs.Count);
         
        }
 
     
     
 
    }
 
    public List<PlayerConfiguration> GetPlayerConfigs()
    {
 
        return _playerConfigs;
    }
 
    private void Update()
    {
     
    }
 
 
}
 
public class PlayerConfiguration
{
 
    public PlayerConfiguration(UnityEngine.InputSystem.PlayerInput pi)
    {
        PlayerIndex = pi.playerIndex;
        Input = pi;
    }
 
    public UnityEngine.InputSystem.PlayerInput Input { get; set; }
 
    public int PlayerIndex { get; set; }
 
    public bool IsReady { get; set; }
 
    public Material PlayerMaterial { get; set; }
 
    public int Team { get; set; }
 
 
 
}
Dans la deuxième scène, j'ai "InitializeLevel.cs". Ce script fait apparaître les joueurs à différentes positions en fonction de leur équipe.

Code : Tout sélectionner

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
 
public class InitializeLevel : MonoBehaviour
{
 
    [SerializeField] private Transform[] _playerSpawns;
 
    private int _offSet1 = 0;
    private int _offSet2 = 0;
    private int _offSet3 = 0;
    private int _offSet4 = 0;
    private Vector3 _OffSetVector = new Vector3(3.0f, 0f, 0f);
 
    [SerializeField] private GameObject _playerPrefab;
    // Start is called before the first frame update
    void Start()
    {
        var playerConfigs = PlayerConfigurationManager.Instance.GetPlayerConfigs().ToArray();
        for (int i = 0; i < playerConfigs.Length; i++)
        {
            Debug.Log("Player Index : " + playerConfigs[i].PlayerIndex + "is from Team : " + playerConfigs[i].Team);
            switch (playerConfigs[i].Team)
            {
                case 1:
                    _offSet1++;
                    var player1 = Instantiate(_playerPrefab, _playerSpawns[playerConfigs[i].Team-1].position + _offSet1 * _OffSetVector, Quaternion.identity, gameObject.transform);
                    player1.GetComponent<PlayerInputHandler>().InitializePlayer(playerConfigs[i]);
                    break;
             
                case 2:
                    _offSet2++;
                    var player2 = Instantiate(_playerPrefab, _playerSpawns[playerConfigs[i].Team-1].position + _offSet2 * _OffSetVector, Quaternion.identity, gameObject.transform);
                    player2.GetComponent<PlayerInputHandler>().InitializePlayer(playerConfigs[i]);
                    break;
             
                case 3:
                    _offSet3++;
                    var player3 = Instantiate(_playerPrefab, _playerSpawns[playerConfigs[i].Team-1].position + _offSet3 * _OffSetVector, Quaternion.identity, gameObject.transform);
                    player3.GetComponent<PlayerInputHandler>().InitializePlayer(playerConfigs[i]);
                    break;
             
                case 4:
                    _offSet4++;
                    var player4 = Instantiate(_playerPrefab, _playerSpawns[playerConfigs[i].Team-1].position + _offSet4 * _OffSetVector, Quaternion.identity, gameObject.transform);
                    player4.GetComponent<PlayerInputHandler>().InitializePlayer(playerConfigs[i]);
                    break;
             
             
             
            }
 
         
        }
 
    }
 
}
Et chaque joueur dispose du script "PlayerInputHandler.cs". Ce script relie les informations correctes entre le joueur et son personnage (dans le jeu). Il distribue donc correctement les informations contenues dans les PlayerConfigs (index du joeurs, sa team, sa couleur et son contrôleur).

Code : Tout sélectionner

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
 
public class PlayerInputHandler : MonoBehaviour
{
    private PlayerConfiguration _playerConfig;
    private CharacterStateMachine _characterStateMachine;
 
    [SerializeField] private GameObject _playerMesh;
 
    private Player_Input _controls;
 
 
    private void Awake()
    {
     
        _characterStateMachine = GetComponent<CharacterStateMachine>();
        _controls = new Player_Input();
    }
 
    public void InitializePlayer(PlayerConfiguration pc)
    {
        _playerConfig = pc;
        _playerMesh.GetComponentInChildren<Renderer>().material = pc.PlayerMaterial;
        _playerConfig.Input.onActionTriggered += Input_OnActionTriggered;
    }
 
    private void Input_OnActionTriggered(InputAction.CallbackContext obj)
    {
        if (obj.action.name == _controls.CharaControls.Move.name)
        {
            OnMove(obj);
        }
    }
 
    public void OnMove(InputAction.CallbackContext context)
    {
        if (_characterStateMachine != null)
        {
            _characterStateMachine.OnMovementInput(context);
        }
    }
}
On dirait que Unity a besoin d'un joueur contrôlé par un clavier et en plus il DOIT être le joueur 1 (index 0) : "La Tirranie du clavier" :)

Quelqu'un peut-il m'aider à comprendre s'il vous plaît ? Pourquoi, Unity inverse les contrôleurs ?
Dernière édition par Bilu le 02 Oct 2023 11:25, édité 1 fois.

Bilu
Messages : 91
Inscription : 20 Nov 2019 09:24

Re: La tirranie du clavier

Message par Bilu » 02 Oct 2023 11:24

Le problème vient de mon script où j'essaie de passer une variable "PlayerInput" ce qui n'est pas possible. Il n'y a aucun problème avec les autres type de variables présents dans mon script mais "PlayerInput" est un type qui ne peut être passé de cette façon sauf en utilisant des "DontDestroy On load" mais cela ne m'arrange pas dans mon projet.
J'utilise donc des public static Dictionnary pour régler le soucis

Dans la scène de selection d'équipe :

Code : Tout sélectionner

 
    public static Dictionary<int, InputDevice> _playerController = new Dictionary<int,InputDevice>();
    public static Dictionary<int, List<string>> playerSelectionNames = new Dictionary<int, List<string>>();
    public static Dictionary<int, string> _playerControlSchemes = new Dictionary<int, string>();
 
  .
  .
  . 
    public void SetPlayerController(int index, UnityEngine.InputSystem.PlayerInput controller)
    {
     
     
        _playerController.Add(index, controller.devices[0]);
        _playerControlSchemes.Add(index, controller.currentControlScheme);
       
    }
 
  
}
Et dans la deuxième scène, pour réattribuer le bon contrôleur au bon joueur, on utilise :

Code : Tout sélectionner

player1 = UnityEngine.InputSystem.PlayerInput.Instantiate(_playerPrefab, player.Key, playerControlScheme, -1, playerController);

Répondre

Revenir vers « Scripting »