Blissm Geschrieben 22. Juli 2020 Melden Share Geschrieben 22. Juli 2020 Heyho, ich hab's geschafft..! ...oder auch nicht. đ Aber der Reihe nach.. Bei meinem Projekt Mega Bliss Bros. habe ich schon seit längerer Zeit versucht eine Charakter-Auswahl im Titel-MenĂź zu integrieren, und nach vielen Versuchen und vielem Lernen hab ich es jetzt auch tatsächlich geschafft. Jedoch wartete dort natĂźrlich gleich schon der nächste Fehler auf mich.. đŹ Nämlich kann ich zwar mit jedem der Charaktere spielen und auch von Level zu Level weiter springen, aber wenn der Charakter stirbt will er einfach nicht mehr respawnen. Es hängt dann in Dauerschleife in der Todes-Animation fest anstatt dass es den Animator triggert zu respawnen. đ¤ˇââď¸ Animator is not playing an AnimatorController UnityEngine.Animator:SetTrigger(String) CharacterController2D:Respawn(Vector3) (at Assets/Scripts/CharacterController2D.cs:306) GameManager:ResetGame() (at Assets/Scripts/GameManager.cs:192) <KillPlayer>c__Iterator0:MoveNext() (at Assets/Scripts/CharacterController2D.cs:267) UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) Das ist was mit die Konsole dazu ausspuckt. Das Auswählen der Charaktere funktioniert Ăźber die PlayerPrefs mit SetInt und GetInt. Jeder Charakter hat den Character-Controller Skript mit individuellen Anpassungen, jeder ist als "Player" getaggt und ihr gemeinsames Parent hat den Character-Selection Skript. Die Spielfigur wird durch den "Player"-Tag erkannt. Ausschnitt aus dem Character-Controller Skript: // (...) // public function to apply damage to the player public void ApplyDamage (int damage) { if (playerCanMove) { playerHealth -= damage; if (playerHealth <= 0) { // player is now dead, so start dying PlaySound(deathSFX); StartCoroutine (KillPlayer ()); } } } // public function to kill the player when they have a fall death public void FallDeath () { if (playerCanMove) { playerHealth = 0; PlaySound(fallSFX); StartCoroutine (KillPlayer ()); } } // coroutine to kill the player IEnumerator KillPlayer() { if (playerCanMove) { // freeze the player FreezeMotion(); // play the death animation _animator.SetTrigger("Death"); // After waiting tell the GameManager to reset the game yield return new WaitForSeconds(2.0f); if (GameManager.gm) // if the gameManager is available, tell it to reset the game GameManager.gm.ResetGame(); else // otherwise, just reload the current level SceneManager.LoadScene(SceneManager.GetActiveScene().name); } } // (...) // public function to respawn the player at the appropriate location public void Respawn(Vector3 spawnloc) { UnFreezeMotion(); playerHealth = 1; _transform.parent = null; _transform.position = spawnloc; _animator.SetTrigger("Respawn"); } // (...) Ausschnitt aus dem Game-Manager Skript: // (...) Vector3 _spawnLocation; // (...) // set things up here void Awake () { // setup reference to game manager if (gm == null) gm = this.GetComponent<GameManager>(); // setup all the variables, the UI, and provide errors if things not setup properly. setupDefaults(); } // (...) // setup all the variables, the UI, and provide errors if things not setup properly. void setupDefaults() { // setup reference to player if (_player == null) _player = GameObject.FindGameObjectWithTag("Player"); // (...) // get current scene _scene = SceneManager.GetActiveScene(); // get initial _spawnLocation based on initial position of player _spawnLocation = _player.transform.position; // (...) // get the UI ready for the game refreshGUI(); } // (...) // public function to remove player life and reset game accordingly public void ResetGame() { // remove life and update GUI lives--; refreshGUI(); if (lives<=0) { // no more lives // save the current player prefs before going to GameOver PlayerPrefManager.SavePlayerState(score,highscore,lives); // load the gameOver screen SceneManager.LoadScene(levelAfterGameOver); } else { // tell the player to respawn _player.GetComponent<CharacterController2D>().Respawn(_spawnLocation); } } Hoffe die Ausschnitte sind brauchbar. đ  Aber da es mit einem einzelnen Charakter ja einwandfrei funktioniert hat, denke ich dass die anderen Sachen irrelevant sind. Jedenfalls komme ich hier nicht weiter, aber vielleicht habt ihr ja eine Idee..? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 24. Juli 2020 Melden Share Geschrieben 24. Juli 2020 Ich denke wir brauchen noch mehr Informationen um zu helfen, bei den aktuell gezeigten Codeteilen fällt mir nichts auf. Die Fehlermeldung besagt, daĂ am aktuellen GameObjekt zwar ein Animator hängt aber dieser keinen Controller hat und daher der Aufruf: _animator.SetTrigger("Respawn"); ins Leere geht. Dein Problem liegt aber vermutlich woanders. Ich denke das das GameObjekt (mit dem entsprechend ausgewählten Spieler) fĂźr den Respawn-ProzeĂ nicht richtig konfiguriert ist. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 Hmmm, also während diese Meldung kommt wird mir im Animator selbst angezeigt was er macht. Scheint alles normal, abgesehen von dem Respawn. Das seltsame ist dass es funktioniert wenn der Charakter der gespielt wird voher in der Szene schon aktiv ist, aber wiederum nicht wenn auch nur ein weiterer aktiv ist, oder garkeiner. Und ich hab festgestellt dass wenn dieser eine Charakter aktiv ist, ich aber einen anderen im MenĂź anwähle zum spielen, ich diesen zwar auch spielen kann, aber bei einem Tod der zuvor aktivierte respawnt anstelle des Charakters den ich gerade gespielt habe. (Er ist jedoch inaktiv, weil durch den Int ja der andere aktiviert ist. Ich merk es nur daran, dass er den Parent verlässt.) HeiĂt das dass das Spiel einfach nach dem falschen Controller sucht..? Aber was kann ich da machen? đ¤Â Sollte ich vielleicht den Parent respawnen, anstelle des Charakters selbst? (Andererseits hat der mit dem Animator ja nix zu tun..) đ Achja.. und _animator.SetTrigger("Victory"); funktioniert ganz normal. Das find ich auch äuĂerst kurios in Anbetracht dessen das behauptet wird da wäre kein Controller. Ich schau mal ob ich noch was zum zeigen finden kann, aber eigentlich hab ich alles zum Thema Animator und Respawn oben schon drin.. đ¤ˇââď¸ Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 Ich vermute mal du hast nur einen Animator aber mehrere Spieler. Beim Respawn hängt der Character-Controller dann vermutlich an einem Spieler der keinen gĂźltigen Animation-Controller hat (und daher kann er die Respawn-Animation nicht ausfĂźhren und wirft diese Fehlermeldung). Das sind aber alles nur Vermutungen, da ich die Objekt-Hierarchie in deinem Game nicht kenne. Ăndere deinen Quellcode mal wie folgt ab und klicke auf die geworfene Fehlermeldung, dann sollte er das entsprechende GO anspringen welches den Fehler verursacht (alle AusfĂźhrungen werden an dieser Stelle unterbrochen, damit du dir die Situation in Ruhe anschauen kannst):  // public function to respawn the player at the appropriate location public void Respawn(Vector3 spawnloc) { UnFreezeMotion(); playerHealth = 1; _transform.parent = null; _transform.position = spawnloc; if (_animator.runtimeAnimatorController==null) { Debug.Log("Animation-Controller ist nicht korrekt gesetzt! (Klick mich)", gameObject); Debug.Break(); } else { _animator.SetTrigger("Respawn"); } }  Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 Ăndert leider nix. Kommt nur die gleiche Fehlermeldung wie vorher. Es hat auch jeder Charakter seinen ganz persĂśnlichen Animation-Controller. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 Wenn er in den Debug nicht reinläuft, dann setz den Debug mal so: // public function to respawn the player at the appropriate location public void Respawn(Vector3 spawnloc) { UnFreezeMotion(); playerHealth = 1; _transform.parent = null; _transform.position = spawnloc; _animator.SetTrigger("Respawn"); Debug.Log("Animation-Controller ist nicht korrekt gesetzt! (Klick mich)", gameObject); Debug.Break(); } Kann es sein, daà der Charakter deaktviert wurde und im Skript dann versucht wird auf einen inaktiven Controller zuzugreifen? Wenn die FM kommt und du in den Debug.Break() reinläufst schau dir mal das Objekt an indem du dann auf die Logausgabe klickst... PS: Warum nimmt er im Respawn den Parent zu "Player" weg, dass macht irgendwie keinen Sinn, da alle Charaktere unter "Player" liegen sollten? Wenn ich die Technik so sehe, dann sollte immer 1 GO (= der Charakter) unter dem Player aktiv sein. In der Charakterauswahl werden dann nur die GOs unter dem "Player"-GO aktiviert oder deaktivert, also so, dass immer ein GO unter "Player" aktiv ist. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 Huuuch, auf einmal kommt jetzt doch ne andere Fehlermeldung (ohne dass ich jetzt nochmal was geändert hätte đ¤¨) anstatt der voherigen, nämlich: NullReferenceException: Object reference not set to an instance of an object GameManager.ResetGame () (at Assets/Scripts/GameManager.cs:192) CharacterController2D+<KillPlayer>c__Iterator0.MoveNext () (at Assets/Scripts/CharacterController2D.cs:267) UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17) Aach, welche der beiden Meldungen kommt hängt davon ab, ob ich die Charaktere alle an oder aus hab. Wenn sie alle aktiviert sind zum Start dann kommt das mit dem Animator. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 _player.GetComponent<CharacterController2D>().Respawn(_spawnLocation); Dein GameManager muss eine Referenz auf 1 aktives GO (=Character) unter "Player" haben ansonsten geht dieser Aufruf da schief. Zu jeder Zeit sollte unter "Player" 1 aktives GO sein (= der aktive Charakter) wenn das nicht so ist läuft etwas schief. Geh am besten mal auf deinen GameManager und mach den aktiven Spieler (= Variable "_player") dort "public" damit du siehst, welcher Charakter gerade aktiv sein sollte. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 Er nimmt nich den parent von "Player" weg sondern den parent vom Charakter, also das "Player"-Objekt. Das hier ist der komplette Selection-Script: using System.Collections; using System.Collections.Generic; using UnityEngine; // based primary on a quick tutorial by "N3K EN" public class CharacterSelection : MonoBehaviour { private GameObject[] characterList; private int indexx; private void Start() { indexx = PlayerPrefs.GetInt("CharacterSelected"); characterList = new GameObject[transform.childCount]; // TEST characterList[1].SetActive(true); TEST // // Fill the array with our characters for (int i = 0; i < transform.childCount; i++) characterList[i] = transform.GetChild(i).gameObject; // Toggle off their renderer foreach (GameObject go in characterList) go.SetActive(false); // Toggle on the selected character if (characterList[indexx]) characterList[indexx].SetActive(true); } public void ChangeCharacter(int index) { indexx = index; PlayerPrefs.SetInt("CharacterSelected", index); int myPrefsValue = PlayerPrefs.GetInt("CharacterSelected"); } Beim laden der Scene wird der entsprechende Charakter je nach int aktiviert, was auch funktioniert. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 vor 1 Minute schrieb Blissm: Er nimmt nich den parent von "Player" weg sondern den parent vom Charakter, also das "Player"-Objekt. Das hier ist der komplette Selection-Script: Beim laden der Scene wird der entsprechende Charakter je nach int aktiviert, was auch funktioniert. Mein ich ja macht keinen Sinn, wozu? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 Was in der CharacterSelection fehlt ist das Aktualisieren des GameManagers, der halt eine Referenz auf den aktiven Charakter und die wird oben nicht neu gesetzt! Poste mal den Quellcode vom GameManager vor allen wo er die Referenzen setzt. Und geh mal auf deinen GameManager-Code und mach den aktiven Spieler (= Variable "_player") dort "public" damit du siehst, welcher Charakter gerade aktiv ist, dieser sollte dem Charakter entsprechen den du ausgewählt hast. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 Hmm, stimmt.. đ¤Â Das mit dem herausnehmen kapier ich auch nicht.. đ sieht jedenfalls so hier aus:  Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 Der Inspector steht noch auf "June" so sieht man nix. Macht fĂźr mich jedenfalls kein Sinn den C (Charakter) vom Parent zu lĂśsen. Glaub aber das Problem liegt eher am GameManager.... siehe Kommentare oben Sowas fehlt meiner Meinung nach (ist nur eine fiktive Methode da ich die GameManager-Klasse nicht kenne): // Toggle on the selected character if (characterList[indexx]) { characterList[indexx].SetActive(true); GameManager.gm.SetActivePlayer(characterList[indexx]); // oder GameManager.gm._player = characterList[indexx]; } Â Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 "June" war dort gerade der Charakter den ich gespielt habe, der nicht respawnen wollte. Stattdessen ist der Charakter "Pulli" rausgesprungen. đ¤ˇââď¸ Das mit dem GameManager schau ich mir jetzt nochmal an. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 Bedeutet dein GameManager stand auf "Pulli" also auf dem falschen C. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 Tatsache, im Inspector hat er Pulli drin. Wenn ich zu Beginn jedoch jeden Charakter inaktiv habe, bleibt das Feld leer. Der GameManager sucht den Spieler nach Tag, weil ich mir nicht besser zu helfen wusste. đ Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 25. Juli 2020 Autor Melden Share Geschrieben 25. Juli 2020 Ist es eigentlich normal dass der GameManager Skript inaktiv wird, sobald man auf Play drßckt..? Oder ist das nur wegen des Fehlers? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 Eine Exception, die in einem MonoBehaviour-Event (Start, Update, ...) fliegt (und nicht gefangen wird), sorgt in der Tat dafĂźr, dass die Komponente deaktiviert wird. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 25. Juli 2020 Melden Share Geschrieben 25. Juli 2020 Hier eine Ănderung fĂźr deinen GameManager. Dabei musst du danach alle deine Charaktere den GameManager in dem neuen Array zuweisen! Sollte dein GameManager Ăźber die Szenen hinweg aber nicht persistent sein, dann ist es aber ggf. nicht die optimalste LĂśsung, da du dann hier in jeder Szene diese Referenzen neu setzen mĂźsstest... (sollte der GameManager in jeder neuen Szene neu erzeugt werden, dann mĂźsstest du doch wieder Ăźber den Childs des GOs "Player" gehen) public GameObject[] characters; // Hier alle Charaktere zuweisen im Inspector void setupDefaults() { int selected = PlayerPrefs.GetInt("CharacterSelected", 0); // Alle Charaktere deaktiveren foreach (GameObject character in characters) { character.SetActive(false); } // Gewählten Charakter aktivieren (startet bei 0!) characters[selected].SetActive(true); // setup reference to player _player = characters[selected]; //if (_player == null) _player = GameObject.FindGameObjectWithTag("Player"); }  Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Blissm Geschrieben 28. Juli 2020 Autor Melden Share Geschrieben 28. Juli 2020 Soo, hab das jetzt mal ausprobiert. Funktioniert jetzt einwandfrei~ đ Danke schonmal fĂźr die groooĂe Hilfe! Aber ja, ich muss es bei jeder Szene einzeln angeben. Beim GameManager trag ich nämlich unter anderem auch immer den Level ein der als nächstes geladen werden soll.  Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und fĂźr weitere Antworten gesperrt.