首页 > 解决方案 > 为什么我的高分无论如何都会改变?

问题描述

我使用统一来创建游戏。当玩家死亡时,游戏结束场景被加载。无论发生什么,高分始终设置为分数值。为什么?

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

public class HighScoreText : MonoBehaviour
{
    int score;
    int highScore;
    Text text;

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

    // Update is called once per frame
    void Update()
    {
        score = Score.score;

        if(score > highScore)
        {
            highScore = score;
        }

        text.text = highScore.ToString();
    }
}

标签: c#unity3d

解决方案


了解加载场景甚至重新加载场景时会发生什么非常重要。

理解 start 不是构造函数也很重要。它被称为在调用任何更新方法之前启用脚本的第一帧,您可以在此处阅读更多信息:https ://docs.unity3d.com/ScriptReference/MonoBehaviour.Start.html

因此,让我们分析您的问题,加载 gameOverScene,它首先创建所有游戏对象并初始化脚本。这包括您的 highScoreText 对象(附加此脚本的游戏对象)。现在我们有了一个叫做 Scope 的东西。可以有 2 个单独的 highScoreObjects,它们每个都有自己的 highscore 值,因为脚本中的每个值都不是共享的全局值或静态值。还有一点需要注意,因为这个值不是静态的并且是单个对象的成员,所以当场景被卸载时,场景中的所有对象都会被销毁。这意味着您为高分存储的值将被删除。

所以场景被创建,如果它们不是静态的,你的对象将使用它们的默认值创建。场景被破坏,你的所有对象都被破坏,你存储在它们上的所有值也被破坏。因此,解决方案是找到一种方法来保持该值在场景中的持久性......似乎根据上面的评论以及我所说的关于静态值的内容,我们有一些选择......

1 选项是使高分静态,现在该值不会在场景变化时被破坏......但它在所有高分选项之间共享......

另一种选择是制作一个单例,单例的统一模式是通常有一个用 (DontDestroyOnLoad) 标记的游戏对象,然后在启动方法中检测这个单例是否存在,如果它确实存在并且它不是我,则摧毁我自己。如果它不能成为我。

就个人而言,由于我不知道您项目的全部范围,我只会将它存储在您已经创建的名为“Score”的类中,使其成为静态,为其创建一个访问器,以及一个检查当前分数是否更大的方法highscore 然后返回例如:

class Score {
    public static int score;
    private static int highScore;

    public static void CheckForNewHighScore() {
        if(score > highScore)
        {
            highScore = score;
        }
    }

    public static int getHighScore()
    {
        return highScore;
    }
}

这将解决您在重新加载场景时丢失信息的问题,并保持高分......

有了这个,你还可以将你的 highScoreText 类更改为这样的东西

public class HighScoreText : MonoBehaviour
{
    Text text;

    // Start is called before the first frame update
    void Start()
    {
        Score.CheckForNewHighScore();
        int currentHighScore = Score.getHighScore();
        text = GetComponent<Text>();
        if(text != null) {

             text.text = currentHighScore .ToString();
        }
    }

    // Update is called once per frame
    void Update()
    {
        // Removed everything from here because... well if they are 
        // on the gameover screen their score shouldn't increase 
        // So no reason to keep reseting the value.
    }
}

推荐阅读