Jump to content
Unity Insider Forum

Score und Highscore erstellen


ShV

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;
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • Antworten 52
  • Created
  • Letzte Antwort
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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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");
        }
        
        

        
    }
Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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());
    }
    
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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");
        }
    
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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";
Link zu diesem Kommentar
Auf anderen Seiten teilen

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!

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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);
    }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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?

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

Ankündigungen


Hy, wir programmieren für dich Apps(Android & iOS):

Weiterleitung zum Entwickler "daubit"



×
×
  • Neu erstellen...