[2D] Gestion de plusieurs personnages

Pour les scripts écrits en C#
Règles du forum
Merci de respecter la NOMENCLATURE suivante pour vos TITRES de messages :

Commencez par le niveau de vos scripts
DB = Débutant
MY = Moyen
CF = Confirmé

Puis le domaine d'application
-RS = Réseau
-AL = Algorithmie

Exemple :

[DB-RS] Mouvement perso multijoueur
Avatar de l’utilisateur
Zankior
Messages : 5
Inscription : 16 Mars 2015 23:17

[2D] Gestion de plusieurs personnages

Message par Zankior » 31 Mars 2015 01:22

Bonsoir à tous,

Je me retrouve aujourd'hui face à un problème, et j’espérais que vous pourriez m'aider à m'en sortir.

Tout d'abord le contexte :
- J'ai crée 2 personnages, Player et Player2. Un seul personnage doit être affiché, et à l'appui sur une touche, j’échange les personnages
- Ils ont chacun leurs animation, et un script chacun pour gérer leurs déplacements"PlayerScript" et "Player2Script". (C'est pas forcément optimiser mais je vais partir comme cela pour l'instant)
- J'ai un script lié à une caméra "Scrolling" qui suit le joueur. Si changement de joueur :

Code : Tout sélectionner

		if(PlayerManager.CurrentPlayer==false)
			playerT=GameObject.Find("Player").transform;

		if(PlayerManager.CurrentPlayer==true)
			playerT=GameObject.Find("Player2").transform;
(Ce n'est qu'une partie du script)

- J'ai un autre script "PlayerManager", dans lequel je veux gérer le changement de personnage comme cela :
  • Appui sur X
  • Mettre Player2 à la position de Player
  • Désactiver Player
  • Activer Player2
  • CurrentPlayer=1
- Dans PlayerManager, j'ai une variable booléenne "CurrentPlayer". Elle sera à 0 quand on utilise "Player" et à 1 quand on utilise "Player2"

Mon problème est le suivant : Pour le script Player Manager, je veux récupérer plusieurs informations de mes objets "Player" et "Player2" : La position du transform en x et y, pouvoir activer/désactiver l'objet. Mais je ne sais pas comment m'y prendre pour avoir ces informations

Voici mon code actuel

Code : Tout sélectionner

using UnityEngine;
using System.Collections;

public class PlayerManager : MonoBehaviour {

	public static bool CurrentPlayer=false;
	private PlayerScript player;
	private Player2Script player2;
	// Use this for initialization
	void Start () {
		player = (GameObject)FindObjectOfType (typeof(PlayerScript));
		player2 = (GameObject)FindObjectOfType(typeof(Player2Script));
		player2.gameObject.SetActive (false);
	}
	
	// Update is called once per frame
	void Update () {

	if (Input.GetKey ("X") && CurrentPlayer == false) {

			player.gameObject.SetActive (false);
			player2.transform.position.x=player.transform.position.x;
			player2.transform.position.y=player.transform.position.y;
			CurrentPlayer = true;
			player2.gameObject.SetActive (true);
		}
		if (Input.GetKey ("X") && CurrentPlayer == true) {
			
			player2.gameObject.SetActive (false);
			player.transform.position.x=player2.transform.position.x;
			player.transform.position.y=player2.transform.position.y;
			CurrentPlayer = false;
			player.gameObject.SetActive (true);
		}
	}
}
Mais j'ai plusieurs erreurs et je pense m'y prendre mal, vous auriez des idées ?

Merci d'avance :D

Ernest
Messages : 11
Inscription : 23 Mars 2015 10:43

Re: [2D] Gestion de plusieurs personnages

Message par Ernest » 31 Mars 2015 09:38

Je pense (car tu ne donnes aucune indication) que ton problème principal est que dans ton Update(), tu switch plusieurs (plein) de fois d'une condition à l'autre. Si tu veux changer une fois de perso à chaque fois que tu appuis sur Espace, utilise plutôt la fonction Input.GetKeyDown().

Avatar de l’utilisateur
Zankior
Messages : 5
Inscription : 16 Mars 2015 23:17

Re: [2D] Gestion de plusieurs personnages

Message par Zankior » 31 Mars 2015 13:50

Mon problème n'était pas celui-là, mais la remarque est pertinente, je vais changer celà.
Non le problème est que mon script me retourne une erreur Cs0029, au niveau du findObjectOfType.
C'est en celà que je dis que je penses m'y prendre mal, au niveau de l'acquisition des données de mes objets

Ernest
Messages : 11
Inscription : 23 Mars 2015 10:43

Re: [2D] Gestion de plusieurs personnages

Message par Ernest » 31 Mars 2015 13:55

Tu es sur Unity5?
Je ne pourrais pas t'aider le cas échéant, mais sinon utilise cette fonction comme ceci:

Code : Tout sélectionner

Type var = GameObject.FindObjectOfType<Type>();

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6224
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: [2D] Gestion de plusieurs personnages

Message par boubouk50 » 31 Mars 2015 15:00

Ce qui ressort de l'erreur c'est une erreur de Cast.

Code : Tout sélectionner

player = (GameObject)FindObjectOfType (typeof(PlayerScript));
player2 = (GameObject)FindObjectOfType (typeof(Player2Script));
Je ne suis pas sur du cast direct en GameObject... Il faut passer par plusieurs lignes
Tu devrais essayer:

Code : Tout sélectionner

PlayerScript temp =  (PlayerScript) FindObjectOfType (typeof(PlayerScript));
player = temp.gameObject;
Voire ça, mais je ne suis pas sur du tout.

Code : Tout sélectionner

player = FindObjectOfType (typeof(PlayerScript)).gameObject;
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
Zankior
Messages : 5
Inscription : 16 Mars 2015 23:17

Re: [2D] Gestion de plusieurs personnages

Message par Zankior » 31 Mars 2015 23:44

Je suis effectivement sur unity 5
J'ai essayé, mais j'avais toujours mes erreurs de Script. Après moults tentative, j'ai réussi à avoir un script sans erreurs.

Code : Tout sélectionner

using UnityEngine;
using System.Collections;
using System;

public class PlayerManager : MonoBehaviour {

	public static bool CurrentPlayer=false;
	private GameObject player;
	private GameObject player2;
	Transform PlayerTransform;
	Transform Player2Transform;
	// Use this for initialization
	void Start () {
		PlayerScript temp =  (PlayerScript) FindObjectOfType (typeof(PlayerScript));
		player = temp.gameObject;
		PlayerTransform=player.transform;

		Player2Script temp2 =  (Player2Script) FindObjectOfType (typeof(Player2Script));
		player2 = temp2.gameObject;
		Player2Transform=player2.transform;

		player2.gameObject.SetActive (false);
	}
	
	// Update is called once per frame
	void FixedUpdate () {

		/*Player vers Player2*/
	if (Input.GetKeyDown ("x") && CurrentPlayer == false) {

			player.gameObject.SetActive (false);
			Player2Transform.position=PlayerTransform.position;
			Player2Transform.position=PlayerTransform.position;
			CurrentPlayer = true;
			player2.gameObject.SetActive (true);
		}

		/*Player2 vers Player*/
		if (Input.GetKeyDown ("x") && CurrentPlayer == true) {
			
			player2.gameObject.SetActive (false);
			player.transform.position=player2.transform.position;
			player.transform.position=player2.transform.position;
			CurrentPlayer = false;
			player.gameObject.SetActive (true);
		}
	}
}
Mais j'ai un problème : Mes personnages ne sont pas échangés, j'ai l'impression que le Player est seulement désactiver puis réactiver.
Je vais essayer de paramétrer VisualStudio pour Unity, j'ai beaucoup de bug avec les debuger d'unity, pas moyen de voir quoi que ce soit

Avatar de l’utilisateur
giyomuSan
Messages : 1799
Inscription : 09 Déc 2009 14:52
Localisation : Japon

Re: [2D] Gestion de plusieurs personnages

Message par giyomuSan » 01 Avr 2015 04:39

tiens si ca peu t aider , voici une version de ce que tu veux faire qui fonctionne.

je vois pas l interet du FixedUpdate ( surtout pour process des input ) , le fixedUpdate generalment s utilise seulement pour la physique.

aussi pour chopper tes player , les tags sont plus efficaces, tel que tu cherche tes player ca veux dire que tu as 2 script different alors que tes player ont certainement les meme functionalitees..dans ce cas un seul script "player" sera mieux approprie non ?

le script fonctionne, tu a juste a pas oublier de creer les tags

Code : Tout sélectionner

using UnityEngine;
using System.Collections;

public class PlayerManager : MonoBehaviour 
{
	#region fields
	[SerializeField]
	private bool currentPlayer = true;

	private Transform player1;
	private Transform player2;

	private const string PLAYER1_TAG = "Player1";
	private const string PLAYER2_TAG = "Player2";
	#endregion

	#region properties
	// dans le cas ou tu vexu acceder a cet valeur depuis un autre script
	public bool CurrentPlayer
	{
		set
		{
			currentPlayer = value;
			SwitchPlayer();
		}
	}
	#endregion

	#region methods
	void Start()
	{
		player1 = GameObject.FindWithTag(PLAYER1_TAG).transform;
		player2 = GameObject.FindWithTag(PLAYER2_TAG).transform;

		if(player1 == null || player2 == null)
		{
			Debug.LogError("Initialization failed in : " + this.GetType().ToString());
			return;
		}

		SwitchPlayer();
	}

	void SwitchPlayer()
	{
		if (!currentPlayer) player2.position = player1.position;
		else player1.position = player2.position;

		// Dans ton cas tu considere que pour true , player1 est active t player2 est deactive, et vice versa
		player1.gameObject.SetActive(currentPlayer);
		player2.gameObject.SetActive(!currentPlayer);

		currentPlayer = !currentPlayer;
	}

	void Update()
	{
		if (Input.GetKeyDown(KeyCode.X)) SwitchPlayer();
	}
	#endregion
}
Je pense aussi que tu devrais eviter le bool pour le flag , c source de confusion assez rapidement qd tu commence a avoir pas mal de code ou tu dois le gerer.

a la place ton currentPlayer pourrais juste etre de Type transform

ca donnerais ca

Code : Tout sélectionner

using UnityEngine;
using System.Collections;

public class PlayerManager : MonoBehaviour 
{
	#region fields
	[SerializeField]
	private Transform currentPlayer;

	private Transform player1;
	private Transform player2;

	private const string PLAYER1_TAG = "Player1";
	private const string PLAYER2_TAG = "Player2";
	#endregion

	#region methods
	void Start()
	{
		player1 = GameObject.FindWithTag(PLAYER1_TAG).transform;
		player2 = GameObject.FindWithTag(PLAYER2_TAG).transform;

		if(player1 == null || player2 == null)
		{
			Debug.LogError("Initialization failed in : " + this.GetType().ToString());
			return;
		}

		SwitchPlayer();
	}

	void SwitchPlayer()
	{
		// default si le currentPlayer est null
		if(currentPlayer == null) currentPlayer = player2;

		// garde la position courante du player et on le deactive
		var currenPosition = currentPlayer.position;
		currentPlayer.gameObject.SetActive(false);

		// switch de player et update la position du nouveau player
		currentPlayer = currentPlayer.Equals(player1) ? player2 : player1;
		currentPlayer.position = currenPosition;

		// on active le nouveau player a l ecran
		currentPlayer.gameObject.SetActive(true);
	}

	void Update()
	{
		if (Input.GetKeyDown(KeyCode.X)) SwitchPlayer();
	}
	#endregion
}

Avatar de l’utilisateur
Zankior
Messages : 5
Inscription : 16 Mars 2015 23:17

Re: [2D] Gestion de plusieurs personnages

Message par Zankior » 06 Avr 2015 21:59

Salut,

Après tout ce temps, j'ai enfin eu le temps de regarder ce que tu m'as envoyé, et après quelques modifications ça marche parfaitement.
J'ai d'abord eu un petit soucis pour récupérer la variable CurrentPlayer sur un autre script, mais j'ai réussi au final.

Par-contre pourrais-tu m'expliquer ce qu'est "SerializeField" ?
Et pourquoi appeler SwitchPlayer dans le set au début ?

Merci d'avance :D

Avatar de l’utilisateur
giyomuSan
Messages : 1799
Inscription : 09 Déc 2009 14:52
Localisation : Japon

Re: [2D] Gestion de plusieurs personnages

Message par giyomuSan » 07 Avr 2015 15:29

Zankior a écrit :Salut,

Après tout ce temps, j'ai enfin eu le temps de regarder ce que tu m'as envoyé, et après quelques modifications ça marche parfaitement.
J'ai d'abord eu un petit soucis pour récupérer la variable CurrentPlayer sur un autre script, mais j'ai réussi au final.

Par-contre pourrais-tu m'expliquer ce qu'est "SerializeField" ?
Et pourquoi appeler SwitchPlayer dans le set au début ?

Merci d'avance :D
[SerializedField] ca entre autre te permet de voir une variable prive expose dans l inspecteur.

Si tu modifie le property CurrentPlayer depuis un script exterieur , c censer aussi switcher le player, la fct SwitchPlayer est pas public donc pas accessible et dans le sens ou logiquement modifier CurrentPlayer devrais forcement aussi operer le switch du player.

Du coup si currentPlayer est modifie de l' exterieur il switch en meme temps le player ( sans avoir besoin d appeler la methode pour le faire )

Maintenant c7est pas une obligation non plus , et si tu actuellement ne fais que lire CurrentPlayer sans jamais le modifier depuis l'exterieur c'est meme pas utile.

Répondre

Revenir vers « (C#) CSharp »