Jump to content
Unity Insider Forum
ShV

Score und Highscore erstellen

Recommended Posts

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

[RequireComponent(typeof(Text))] // Damit kann diese Komponente nur auf GameObjects gelegt werden, die auch eine Textkomponente haben
public class ScoreAnzeige : MonoBehaviour
{
    
    
    
        private Text text;

        private void Awake()
        {
            text = GetComponent<Text>();
            Debug.Log("Wach");
        }

        private void OnEnable()
        {
            Zähler.onScoreChange += UpdateScore; // Reaktion "UpdateScore" hinzufügen
            UpdateScore(Zähler.currentscore); // Gleich mal den aktuellen Wert anzeigen, nicht erst bis zur ersten Änderung warten
            Debug.Log("Score anzeigen");
        }

        private void OnDisable()
        {
            Zähler.onScoreChange += UpdateScore; // Reaktion wieder austragen
            UpdateScore(Zähler.currentscore);
            Debug.Log("onScoreChange");
        }

        private void UpdateScore(int newScore)
        {
            text.text = newScore + "10";
            Debug.Log("Neuer Score");
        }
    
}
 private void OnTriggerEnter2D(Collider2D other)
    {
        if(other.tag == "Collector")
        {
            gameObject.SetActive(false);
            Zähler.currentscore += 10;
            Debug.Log("currentscore");

        }
    }
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System; ///Brauche ich, um die Action-Klasse nutzen zu können
    // Ein Action-Objekt repräsentiert eine Methode, die aufgerufen werden kann. Durch die Verwendung von "event" kann es mehrere methoden auf einmal repräsentieren. Mit += und -= fügt der andere Code eine Methode zum Event hinzu bzw. nimmt sie wieder weg.

public static class Zähler //Statische Variablen und Methoden sind nicht an Objektinstanzen gebunden
{
    private static int _currentscore = 0;
    public static int currentscore
    {
        get { return _currentscore; }
        set
        {
            _currentscore = value; //value ist auf deutsch Wert
            onScoreChange?.Invoke(value);
            Debug.Log("Zählercurrentscore");//Invoke ruft die repräsentierten Methoden auf
        }                                //die gerade hinzugefügt sind
    }

    public static event Action<int> onScoreChange;
}

 

Share this post


Link to post
Share on other sites
text.text = newScore + "10";

Also, falls du dich fragst, warum hinter deiner Punktzahl immer noch eine "10" angehängt ist...

Am 30.4.2020 um 11:03 schrieb ShV:

Die Punktzahl wird auch nicht direkt im Spiel aktuallisiert, sondern erst, wenn ich wieder auf Play gedrückt habe.

Das heißt, dass du noch mehr Code hast, vermutlich mit PlayerPrefs.

Siehst du denn "currentscore" in der Konsole?

Share this post


Link to post
Share on other sites

Nein, sehe ich nicht

Den Code für die PlayerPrefs habe ich auch noch nicht. Der einzige Code, der noch etwas damit zu tun hat ist der:

void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.tag == "Kugel")
        {
            gameObject.SetActive(false);
            Zähler.currentscore += 10; //Mit "Zähler" auf das Script verwiesen und mit "currentscore" auf die Variable im Script
            Debug.Log("Gegnerpunkte");
        }
        
        

        
    }

Share this post


Link to post
Share on other sites
vor 6 Stunden schrieb ShV:

Nein, sehe ich nicht

Dann brauchst du dich ja nicht zu wundern. Offenbar wird dein Trigger nicht ausgelöst. Wenn in diesem Code

if(other.tag == "Collector")
{
  gameObject.SetActive(false);
  Zähler.currentscore += 10;
  Debug.Log("currentscore");
}

nichts in der Konsole auftaucht (und auch keine Fehlermeldung kommt), kannst du davon ausgehen, dass die anderen beiden Zeilen auch nicht ausgeführt werden.

Share this post


Link to post
Share on other sites

Das ist ja das Merkwürdige. Wenn das gameObject auf den Collector trifft, wird es deaktiviert. In der Konsole steht aber trotzdem nichts

Share this post


Link to post
Share on other sites

Hier ist eine kurze Liste aller Dinge, die passieren können, sodass eine Zeile Code ausgeführt wird und eine folgende nicht mehr:

  1. Der Kontrollfluss geht woanders lang (z.B. ein if, oder auch break, continue, return, yield).
  2. Es tritt eine Exception zwischen den beiden Zeilen auf.
  3. Irgendwelcher Humbug mit Multithreading.

3. kommt hier nicht infrage, und 2. würdest du in der Konsole sehen. 1 können wir ausschließen, dafür ist der Code zu simpel.

Bleibt also nur noch eine weitere Möglichkeit: Das da ist gar nicht der Code, der das Objekt deaktiviert. Du scheinst irgendwo noch weiteren Code laufen zu haben, der irgendwelche Dinge tut. Baue am besten mal ein Minimalbeispiel, wo wirklich nichts anderes mehr drin ist.

Share this post


Link to post
Share on other sites

Ich habe jetzt ein neues Projekt nur mit dem Nötigsten erstellt. Jetzt sehe ich auch "currentscore" in der Konsole. Trotzdem wird aber vor der Punktzahl eine 10 angezeigt. Das sind die einzigen, die ich benutze:

public class Gegnerbew : MonoBehaviour
{
    public float speed = -1f;
    private Rigidbody2D myRB;

    // Start is called before the first frame update
    void Start()
    {
        myRB = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        myRB.velocity = new Vector2(speed, 0);
    }
}
public class Gegneroff : MonoBehaviour
{
  
   
    private void OnTriggerEnter2D(Collider2D other)
    {
        if(other.tag == "Collector")
        {
            gameObject.SetActive(false);
            Zähler.currentscore += 10;
            Debug.Log("currentscore");

        }
    }
public class PlayerMovement : MonoBehaviour
{
    public float jumpForce = 3f;

    private Rigidbody2D myRB;
    private bool canJump;
    // Start is called before the first frame update
    void Start()
    {
        myRB = GetComponent<Rigidbody2D>();
       

    }

    //Jump Funktion
    public void Jump()
    {
        //Darf Spieler springen?
        if (canJump)
        {
            canJump = false;
            myRB.velocity = new Vector2(0f, jumpForce);
        }
       
    }
    private void OnCollisionEnter2D(Collision2D other)
    {
        canJump = true;
    }
}

Könnte das vielleicht mit an diesem Scripte liegen, das "curentscore" nicht in der Konsole erscheint?:

 

public class Spawner : MonoBehaviour
{
    public GameObject[] Gegner;
    public List<GameObject> GegnerToSpawn = new List<GameObject>();

    int index;

    private void Awake()
    {
        IniGegner();
    }
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(SpawnRandomGegner());
    }
    void IniGegner()
    {
        index = 0;
        //Initialisiere die Gegner
        for (int i = 0; i < Gegner.Length * 10; i++)
        {
            GameObject obj = Instantiate(Gegner[index], transform.position, Quaternion.identity);
            GegnerToSpawn.Add(obj);
            GegnerToSpawn[i].SetActive(false);
            index++; 

            if (index == Gegner.Length)
            {
                index = 0;
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        
    }
    IEnumerator SpawnRandomGegner()
    {
        //Warte eine gewisse Zeit
        yield return new WaitForSeconds(Random.Range(1.5f, 4.5f));
        //Aktiviere Gegner
        int index = Random.Range(0, GegnerToSpawn.Count);

        while(true)
        {
            if(!GegnerToSpawn[index].activeInHierarchy)
            {
                GegnerToSpawn[index].SetActive(true);
                GegnerToSpawn[index].transform.position = transform.position;
                break;
            }
            else
            {
                index = Random.Range(0, GegnerToSpawn.Count);
            }
        }
        StartCoroutine(SpawnRandomGegner());
    }
    
}

 

Share this post


Link to post
Share on other sites
vor 12 Stunden schrieb ShV:

Trotzdem wird aber vor der Punktzahl eine 10 angezeigt

Wie sieht denn jetzt dein Code aus, in dem der Text gesetzt wird?

 

vor 12 Stunden schrieb ShV:

Könnte das vielleicht mit an diesem Scripte liegen, das "curentscore" nicht in der Konsole erscheint?:

Ich sehe da nichts, was damit zusammenhängen könnte.

Share this post


Link to post
Share on other sites
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(Text))] // Damit kann diese Komponente nur auf GameObjects gelegt werden, die auch eine Textkomponente haben
public class ScoreAnzeige : MonoBehaviour
{
    
    
    
        private Text text;

        private void Awake()
        {
            text = GetComponent<Text>();
            Debug.Log("Wach");
        }

        private void OnEnable()
        {
            Zähler.onScoreChange += UpdateScore; // Reaktion "UpdateScore" hinzufügen
            UpdateScore(Zähler.currentscore); // Gleich mal den aktuellen Wert anzeigen, nicht erst bis zur ersten Änderung warten
            Debug.Log("Score anzeigen");
        }

        private void OnDisable()
        {
            Zähler.onScoreChange += UpdateScore; // Reaktion wieder austragen
            UpdateScore(Zähler.currentscore);
            Debug.Log("onScoreChange");
        }

        private void UpdateScore(int newScore)
        {
            text.text = newScore + "10";
            Debug.Log("Neuer Score");
        }
    
}

 

Share this post


Link to post
Share on other sites

Ich habe in mein Script zum Deaktivieren noch ein Debug.Log reingepackt:

void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.tag == "Kugel")
        {
            gameObject.SetActive(false);
            Debug.Log("inactive");
            Zähler.currentscore += 10; //Mit "Zähler" auf das Script verwiesen und mit "currentscore" auf die Variable im Script
            Debug.Log("Gegnerpunkte");
        }
        
        

        
    }

"inactive wird mir nun in der Konsole angezeigt, aber "Gegnerpunkte" nicht

Share this post


Link to post
Share on other sites
text.text = newScore + "10";

Hast ja immer noch drin. Hab doch oben erklärt, wo hier das Problem ist.

vor 10 Stunden schrieb ShV:

"inactive wird mir nun in der Konsole angezeigt, aber "Gegnerpunkte" nicht

Dann fliegt irgendwo eine Exception. Die muss dann in der Konsole stehen. Oder hast du Fehlermeldungen da rausgefiltert?

Share this post


Link to post
Share on other sites

Immernoch diese Fehlermeldung:

 

Am 30.4.2020 um 11:03 schrieb ShV:

"Missing Reference Exception: The object of type 'Text' has been destroyed but you are still trying to acces it. Your script should either check if it is null or you should not destroy the object".

Und was genau muss ich hiermit machen:

            text.text = newScore + "10";

Share this post


Link to post
Share on other sites

Ach ja, das Ding. Ich dachte, das wäre durch. Du musst halt sicherstellen, dass es in der Szene KEIN GameObject gibt, das eine ScoreAnzeige-Komponente hat, aber keine Text-Komponente. Wenn du 100% sicher bist, dass das der Fall ist, dann hast du irgendwo eine Komponente, die in Awake oder noch früher an der Punktzahl rumbastelt.

vor 23 Minuten schrieb ShV:

Und was genau muss ich hiermit machen:

Komm schon, das hab ich erklärt. Wo kommt diese 10 her? Was macht die da? Mach sie halt weg!

Share this post


Link to post
Share on other sites

Ich habe das Spiel gerade auf mein Handy exportiert und dort aktualisiert sich die Punktzahl direkt. Sie aktualisiert sich nur nicht in Unity. Woran kann das liegen?

Share this post


Link to post
Share on other sites

Daran, dass du irgendwo noch in Awake Code hast, der an der Punktzahl rumbastelt. Die Reihenfolge, in welcher Objekte ihre MonoBehaviour-Events (Awake, Start, Update, ...) aufgerufen kriegen, ist undefiniert und kann sich zwischen Editor und Build gerne mal unterscheiden.

Share this post


Link to post
Share on other sites

Am Handy kommt das Problem auch, aber erst, nachdem der Spieler Gameover ging und ich das Spiel neu gestartet habe. Die alte Punktzahl stand noch da, wurde also nicht auf 0 zurückgesetzt und nicht mehr aktualisiert. Kann es vielleicht sein, dass sich der Code selber behindert?

Share this post


Link to post
Share on other sites

Ich habe jetzt alle Scripts durchgeschaut, aber nichts gefunden. Kannst du hier vielleicht was finden, was damit zusammenhängen könnte?:

public class Shoot : MonoBehaviour
{
    public Transform Bulletspawn;
    Rigidbody2D clone;
    public Rigidbody2D bulletPrefap;
    public float bulletSpeed = 100f;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Attack()
    {
        clone = Instantiate(bulletPrefap, Bulletspawn.position, Bulletspawn.rotation);
        clone.AddForce(Bulletspawn.transform.right * bulletSpeed);

    }
}
public class Kugelgrenze : MonoBehaviour
{
    public float lifespan = 1.3f;
    // Start is called before the first frame update
    void Start()
    {
        Destroy(gameObject, lifespan);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
public class Kugeldelete : MonoBehaviour
{
 
    private void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.tag == "Gegner")
        {
            Destroy(gameObject, 0.01f);
        }
    }



}
 private void OnTriggerEnter2D(Collider2D other)
    {
        if(other.tag == "Collector")
        {
            gameObject.SetActive(false);
            Zähler.currentscore += 10;
            Debug.Log("currentscore");

        }
    }
public class Gegnerbew : MonoBehaviour
{
    public float speed = -1f;
    private Rigidbody2D myRB;

    // Start is called before the first frame update
    void Start()
    {
        myRB = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        myRB.velocity = new Vector2(speed, 0);
    }
}
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.SocialPlatforms.Impl;

public class GameOver : MonoBehaviour
{
    public string sceneToLoad;
   
    public void OnTriggerEnter2D(Collider2D other)
    {
        if(other.tag == "Gegner")
        {
            SceneManager.LoadScene(sceneToLoad);
            var finalscore = Zähler.currentscore;
            PlayerPrefs.SetInt("Highscore", finalscore);
            Debug.Log("Highscore");
        }
        
    }
    
}
public class Fight : MonoBehaviour
{
    public Transform Bulletspawn;
    Rigidbody2D clone;
    public Rigidbody2D bulletPrefap;
    public float bulletSpeed = 100f;
    private readonly int maximaleMunition = 3;
    public int ShotsFired;
    

    // Update is called once per frame
    void Update()
    {
        if (CrossPlatformInputManager.GetButtonDown("Peng"))
        {

            Attack();
        }

    }
   void Attack()
    {
        if (ShotsFired < maximaleMunition)
        {


            clone = Instantiate(bulletPrefap, Bulletspawn.position, Bulletspawn.rotation);
            clone.AddForce(Bulletspawn.transform.right * bulletSpeed);
            ShotsFired++;
        }
        else return;
    }
    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.tag == "NItem")
        {
            ShotsFired--;
        }
    }



}
public class BGLoope : MonoBehaviour
{
    public float speed = 0.1f;

    private Material mat;
    private Vector2 offset = Vector2.zero;
    // Start is called before the first frame update
    void Start()
    {
        mat = GetComponent<Renderer>().material;
        offset = mat.GetTextureOffset("MainTex");
    }

    // Update is called once per frame
    void Update()
    {
        offset.x = offset.x + speed * Time.deltaTime;
        mat.SetTextureOffset("_MainTex", offset);
    }
}

 

Share this post


Link to post
Share on other sites

Nö, ich finde beim Überfliegen nichts. Bau halt mal ein Minimalbeispiel. Nimm solange Dinge aus einer Kopie deiner Szene weg, bis der Fehler weg ist.

Share this post


Link to post
Share on other sites

Habe herausgefunden, woran es liegt. Ich habe ein Hauptmenü, wo man in einer anderen Szene "Play" auswählt, um die Szene zu wechseln und zu spielen. Hier ist das Script, welches dafür zuständig ist:

using UnityEngine.SceneManagement;
public class Play : MonoBehaviour
{
    public string sceneName;
    public void Spielen()
    {
        SceneManager.LoadScene(sceneName);
    }
}

Und wenn ich am Anfang diese Szene deaktiviere, funktioniert alles. Wo liegt also hierbei der Fehler?

Share this post


Link to post
Share on other sites

Keine Ahnung. Passiert das auch, wenn in der Szene mit diesem Script sonst gar nichts ist?

Share this post


Link to post
Share on other sites

Dann weiß ich auch nicht mehr weiter. Da kann ich dann nur sagen: Willkommen in der Welt des Entwickelns, in denen man sich Nacht um Nacht um die Ohren schlagen kann, um am Ende einen Zahlendreher im eigenen Code zu finden. Erste Fortschritte hast du ja immerhin schon.

Share this post


Link to post
Share on other sites

Ok ich habe den Fehler gefunden. Wenn ich aus dem Hauptmenü das erste Mal auf Play drücke, funktioniert alles. Wenn ich aber ein zweites Mal starte, steht noch die Punktzahl vom vorherigen Durchgang (liegt wahrscheinlich daran, dass ich sie noch nicht mit den Playerprefs speichere und nicht zurücksetze). Wie funktioniert das mit den Playerprefs also genau? Wie speichere ich die Punktzahl und wie lasse ich sie dann Anzeigen?

 

Share this post


Link to post
Share on other sites

Mit den Set...-Methoden speicherst du einen Wert, mit den Get...-Methoden holst du ihn wieder heraus. Auf keinen Fall PlayerPrefs benutzen, um Daten von einer Szene in die andere zu schieben, das Ding ist nur dafür da, dass Daten auch noch da sind, wenn das Spiel aus- und wieder angemacht wird.

Share this post


Link to post
Share on other sites

Ok. Und wie mache ich, dass die Punktzahl nach jedem Gameover auf 0 zurückgesetzt wird?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...