2 votes

La boucle foreach n'itère qu'une seule fois ? C# Unity3D

J'essaie d'instancier un préfabriqué d'arbre basé sur des transformations (spécifiquement la position et la rotation) qui sont chargées depuis une base de données firebase.

Le problème est que la boucle foreach ne s'exécute qu'une seule fois alors qu'il y a au total 4 enfants dans snapshot.Children. Je ne comprends pas pourquoi elle ne s'exécute qu'une seule fois.

Voici la méthode

public void GetTrees()
   {
       reference.Child("Player").Child(scenarioName).GetValueAsync().ContinueWith(task =>
       {
           if (task.IsFaulted)
           {
               Debug.LogError("Error");
           }
           else if (task.IsCompleted)
           {
               DataSnapshot snapshot = task.Result;

               foreach (DataSnapshot tree in snapshot.Children)
               {
                   xPos = float.Parse(tree.Child("xPos").Value.ToString());
                   yPos = float.Parse(tree.Child("yPos").Value.ToString());
                   zPos = float.Parse(tree.Child("zPos").Value.ToString());

                   xRot = float.Parse(tree.Child("xRot").Value.ToString());
                   yRot = float.Parse(tree.Child("yRot").Value.ToString());
                   zRot = float.Parse(tree.Child("zRot").Value.ToString());
                   wRot = float.Parse(tree.Child("wRot").Value.ToString());

                   Vector3 loadTreePosition = new Vector3(xPos, yPos, zPos);
                   Quaternion loadTreeRotation = new Quaternion(xRot, yRot, zRot, wRot);

                   //returns the position of Tree 0 (31.63, .03, -38.79)
                   Debug.Log("Tree Positons " + loadTreePosition); 

                   //returns the rotation of Tree 0 (0,0,0,1)
                   Debug.Log("Tree Rotations " + loadTreeRotation);

                   //returns 4
                   Debug.Log(snapshot.ChildrenCount);

                   Instantiate(treePrefab, loadTreePosition, loadTreeRotation);

                   //THIS DOES NOT RETURN ANYTHING 
                   Debug.Log(snapshot.ChildrenCount);
               }
           }
       });
   }

Voici la console avec les déclarations debug.log indiquées dans la méthode debug log console image

Voici les informations de la base de données en json

{
  "Player" : {
    "test" : {
      "Tree 0" : {
        "mesh" : "palm-01 Instance",
        "wRot" : 1,
        "xPos" : 31.629507064819336,
        "xRot" : 0,
        "yPos" : 0.029083967208862305,
        "yRot" : 0,
        "zPos" : -38.7875862121582,
        "zRot" : 0
      },
      "Tree 1" : {
        "mesh" : "palm-01 Instance",
        "wRot" : 1,
        "xPos" : 31.059694290161133,
        "xRot" : 0,
        "yPos" : 0.029083967208862305,
        "yRot" : 0,
        "zPos" : -40.921390533447266,
        "zRot" : 0
      },
      "Tree 2" : {
        "mesh" : "palm-01 Instance",
        "wRot" : 1,
        "xPos" : 31.059694290161133,
        "xRot" : 0,
        "yPos" : 0.029083967208862305,
        "yRot" : 0,
        "zPos" : -40.921390533447266,
        "zRot" : 0
      },
      "Tree 3" : {
        "mesh" : "palm-01 Instance",
        "wRot" : 1,
        "xPos" : 31.46793556213379,
        "xRot" : 0,
        "yPos" : 0.029083967208862305,
        "yRot" : 0,
        "zPos" : -43.42497253417969,
        "zRot" : 0
      }
    }
  }
}

2voto

derHugo Points 12631

La plupart des API d'Unity ne peuvent être exécutées que dans le thread principal d'Unity !

Vous utilisez ContinueWith(Action<Task>))) sans un TaskScheduler

Crée une continuation qui exécute de manière asynchrone lorsque la cible Task complète.

ce qui ne garantit pas que le callback soit appelé sur le thread principal, si bien que le dernier moment est venu à Instantiate il échoue.

Firebase specific for Unity fournit la méthode d'extension de tâche ContinueWithOnMainThread

Méthodes d'extension pour System.Threading.Tasks.Task y System.Threading.Tasks.Task<T> qui permettent à la fonction de continuation d'être exécutée sur le thread principal de Unity.

vous devriez plutôt utiliser ici

reference.Child("Player").Child(scenarioName).GetValueAsync().ContinueWithOnMainThread(task =>
{
    ....
});

En général, assurez-vous que vous n'avez pas désactivé un type de journal dans la console. Vous auriez dû voir un avertissement vous indiquant que Instantiate ne peut pas être utilisé en dehors du thread principal.

1voto

pakeha_by Points 126

Méthode la plus probable Instantiate(treePrefab, loadTreePosition, loadTreeRotation); lance une exception et cela empêche toute nouvelle itération du cycle. Essayez d'emballer Instantiate(); dans try except and log catched exceptions

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X