problème de liste

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
Kaloverian
Messages : 345
Inscription : 10 Août 2016 03:03

problème de liste

Message par Kaloverian » 11 Mars 2024 23:30

bonjour,

Ce script C# me fournit des erreurs lorsque i>=2:

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class problem_list : MonoBehaviour
{
    List<GameObject> ListGrid;
    public GameObject grid;
    public KeyCode appui;
    int i = 0;
    


    // Start is called before the first frame update
    void Start()
    {
        ListGrid = new List<GameObject>();
        ListGrid.Add(grid);
        ListGrid[0] = grid;
      
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(appui))
        {
            i++;
            ListGrid.Add(grid);
            ListGrid[i] = Instantiate(grid);
            ListGrid[i].name = "Grid " + i;
            
      
            if (i >= 2)
             {
            Destroy(ListGrid[i - 2]);
           
            }
            
            
            
     }

  }
 }

tandis que celui très similaire fonctionne:

Code : Tout sélectionner


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class problem_list : MonoBehaviour
{
    List<GameObject> ListGrid;
    public GameObject grid;
    public KeyCode appui;
    int i = 0;
    


    // Start is called before the first frame update
    void Start()
    {
        ListGrid = new List<GameObject>();
        ListGrid.Add(grid);
        ListGrid[0] = grid;
      
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(appui))
        {
            i++;
            ListGrid.Add(grid);
           ListGrid[i]=new GameObject("grid" + i);
      
          if (i >= 2)
            {
            Destroy(ListGrid[i - 2]);
           
           }

     }
   }
 }
Pouvez-vous donner une explication?
Je préfère utiliser Instantiate car ça m'évite de devoir rajouter les mesh et matériaux à chaque objet instancié surtout si l'objet est un préfab complexe.

merci de votre aide

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

Re: problème de liste

Message par boubouk50 » 12 Mars 2024 09:48

Les deux auront les mêmes erreurs.
Tu détruis les gameObjects, mais tu ne les retires pas de la liste.
Que tu passes par Instantiate ou New GameObject, cela revient au même, tu crées un gameObject. Soit l'erreur est ailleurs (un code dupliqué ou autre pendant ton test), soit le prefab est nul, soit tu as mal réalisé ton test.

Sinon, ton utilisation des listes ne va pas du tout, tu ne fais que remplir une liste et détruire des objets dedans, mais à aucun moment, tu te préoccupes de sa taille. Plus tu vas l'utiliser, plus elle va grossir et plus elle aura d'éléments vides qui pourront poser des problèmes.

Ceci étant dit, comme je sens que tu as coupé ton code pour nous mettre que ce qui pourrait nous intéresser, je ne vais pas pouvoir corriger comme il faut au risque de casser le reste. J'espère qu'à aucun autre moment, tu n'affectes i.

Code : Tout sélectionner

      ListGrid.Add(grid);
        ListGrid[0] = grid; // INUTILE -> .Add() a déjà ajouté grid

Code : Tout sélectionner

      ListGrid.Add(grid); //INUTILE -> Ajoute directement l'instance
      ListGrid[i] = Instantiate(grid);
      ListGrid[i].name = "Grid " + i;

Code : Tout sélectionner

      ListGrid.Add(Instantiate(grid));
      ListGrid[i].name = "Grid " + i;
Utiliser une variable pour tenir un compte est risqué, il vaut mieux utiliser la variable .Count de la liste.

Un exemple d'utilisation d'une liste a deux éléments.

Code : Tout sélectionner

if (Input.GetKeyDown(appui))
{
        i++;
        // Ajoute un nouvel element en fin de liste
        ListGrid.Add(Instantiate(grid));
        // Change le nom du gameObject en fin de liste
        ListGrid[ListGrid.Count-1].name = "Grid " + i;

        if (ListGrid.Count >= 2)
        {
        	// Détruit le premier élément
            	Destroy(ListGrid[0]);
            	// Enlève le premier élément de la liste -> Le second devient alors le premier et ta liste a toujours 2 éléments
            	listGrid.RemoveAt(0);
        }
}
"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
Kaloverian
Messages : 345
Inscription : 10 Août 2016 03:03

Re: problème de liste

Message par Kaloverian » 12 Mars 2024 16:29

désolé,ça ne fonctionne toujours pas !
j'ai compris mon erreur:dans la dernière condition,mettre i>=3

code corrigé:

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class problem_list : MonoBehaviour
{
    List<GameObject> ListGrid;
    public GameObject grid;
    public KeyCode appui;
    int i = 0;
    



    // Start is called before the first frame update
    void Start()
    {
        
        ListGrid = new List<GameObject>();
        ListGrid.Add(grid);
    

  }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(appui))
        {
            i++;
          
            ListGrid.Add(grid);
            // Ajoute un nouvel élément en fin de liste
            ListGrid[i] = Instantiate(grid);
            // Change le nom du gameObject en fin de liste
            ListGrid[i].name = "Grid " + i;


            if (i >= 3)
            {
                // Détruit le premier élément
                Destroy(ListGrid[i-2]);
              
            }
          
        }
    }
}
Dernière édition par Kaloverian le 12 Mars 2024 17:23, édité 1 fois.

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

Re: problème de liste

Message par boubouk50 » 12 Mars 2024 16:49

Merci pour ce retour riche en information...
Merci donc de nous dire pourquoi cela ne fonctionne pas, où est l'erreur, etc. Ca ne fonctionne pas, n'est pas une réponse valable.
Néanmoins, il y a une erreur. Il faut faire RemoveAt () et non pas Remove (), puisque je donne l'index et pas le gameObject à enlever.
"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
Kaloverian
Messages : 345
Inscription : 10 Août 2016 03:03

problème de liste(suite)

Message par Kaloverian » 12 Mars 2024 18:49

re bonjour,

J'ai verrouillé à tort le 1er post "problème de liste".

Je ne comprends pas pourquoi ce code agit faussement:

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class problem_list : MonoBehaviour
{
    List<GameObject> ListGrid;
    public GameObject grid;
    public KeyCode appui;
    int i = 0;
    int nb;



    // Start is called before the first frame update
    void Start()
    {
        
        ListGrid = new List<GameObject>();
        ListGrid.Add(grid);
        ListGrid[0] = grid;
        ListGrid[0].name = "Grid " + 0;
        nb = ListGrid.Count;
        print(i + "," + nb);

  }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(appui))
        {
            i++;
          
            ListGrid.Add(grid);
            // Ajoute un nouvel element en fin de liste
          
            ListGrid[i] = Instantiate(grid);
            // Change le nom du gameObject en fin de liste
            ListGrid[i].name = "Grid " + i;

            if (i >= 2)
            {

                ListGrid[i - 2].SetActive(false);//dès que i=3,ListGrid[1]  est SetActive(false) OK mais aussi ListGrid[i] ?


            }

            nb = ListGrid.Count;
            print(i + "," + nb);
        }

        
    }
}
Pour voir + clair,j'ai utilisé SetActive(false) au lieu Destroy.
dès que i=3, ListGrid[1]=ListGrid[i-2] est SetActive(false) :OK !
mais aussi ListGrid ?
Pourquoi cela?

Moi 1971
Messages : 727
Inscription : 29 Sep 2015 13:38

Re: problème de liste(suite)

Message par Moi 1971 » 13 Mars 2024 09:16

Bonjour, le if " if (i >= 2) " commence à 2 et non 3. Il veut dire : "i supérieure OU égal à 2"
Pour avoir à partir de 3 uniquement il faut écrire "if (i > 2)"

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

Re: problème de liste

Message par boubouk50 » 13 Mars 2024 10:46

 ! Message de : boubouk50
C'est exactement le même sujet, merci de ne pas le dupliquer inutilement.
i = 0 au Start () alors qu'une première grille est ajoutée dans la liste. Donc i vaut listGrid.Count-1 donc l'index du dernier élément. C'est pour ça que i >= 2 est actif lorsque le count est supérieur ou égal à 3.

Ce qui ne va pas est que tu ajoutes grid à l'élément 0, alors que tu devrais ajouter Instantiate (grid).
En ajoutant grid, tu ajoutes le prefab directement donc celui que tu instancies. Si tu le désactives ou le supprimes, alors les instances seront désactivées ou impossibles.

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class problem_list : MonoBehaviour
{
	List<GameObject> ListGrid = new List<GameObject>();
	public GameObject grid;
	public KeyCode appui;
	public int maxCount = 3;

	// Start is called before the first frame update
	void Start()
	{
		// Ajout d'une première grille
    		AddGrid ();
	}

	// Fonction d'ajout de grille -> ajout d'une instance du prefab dans la liste + nouveau nom
	private void AddGrid ()
	{
		// Ajout d'une instance
        	ListGrid.Add(Instantiate (grid));
        	// Renommage
        	ListGrid[ListGrid.Count-1].name = "Grid " + ListGrid.Count-1;
	}

	// Fonction de retrait de la grille la plus ancienne -> Suppression du gameObject + retrait de la liste
	private void RemoveGrid ()
	{
		// Tester si l'élément existe avant de le supprimer
		if (ListGrid[0] != null)
        		Destroy (ListGrid[0]);
        		
        	// Dans tous les cas, l'élément 0 est nul, il faut l'enlever de la liste
        	ListGrid.RemoveAt(0);
	}
	
	// Update is called once per frame
	void Update()
	{
		// Si la touche appui est pressée
		if (Input.GetKeyDown(appui))
        	{
			// Ajoute un nouvel element en fin de liste
			AddGrid ();
			
			// Suppression de l'élément le plus vieux si le nombre d'élément maximum est atteint
			if (ListGrid.Count >= maxCount) // si la grille contient 3 éléments on ne garde que les 2 derniers
			{
				RemoveGrid ();
			}
    		}
    	}
}
"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

Répondre

Revenir vers « (C#) CSharp »