建立统一的评分系统

本文关键字:分系统 建立 | 更新日期: 2023-09-27 18:28:59

我目前正在开发一款简单的2D游戏,以了解游戏开发的许多内容。

尽管如此,我还是有一些问题需要创建一个评分系统。

我想每秒钟更新一次分数,每秒钟加1分,比赛结束后停止计数。

我开始写这个

public class scoremanager : MonoBehaviour {
    public int score;
    public GUIText distance;
    void Start () {
        score = 0;
    }
    void Update () {
        StartCoroutine(updateScoreManager(1f, 1));
        distance.text = score.ToString();
    }
    IEnumerator updateScoreManager(float totalTime, int amount) {
        score += amount; 
        yield return new WaitForSeconds (totalTime);
    }
}

问题是GUIText中没有显示任何内容,所以我不知道它是否有效。游戏结束后,我该如何停止计数?

建立统一的评分系统

首先,我认为您应该使用uGUI,因为这是Unity现在接受的UI解决方案:http://blogs.unity3d.com/2014/05/28/overview-of-the-new-ui-system/

我真的不能说你的GUIText有什么问题,因为我不知道位置是否关闭或其他什么,但我可以告诉你如何更好地管理计数。

您不需要使用Update函数,使用Update函数会破坏使用Coroutine更新文本的目的。使用Coroutine可以控制它何时开始更新和何时停止。因此,一个解决方案是完全取消更新功能,这样你就可以更好地控制它:

public class scoremanager : MonoBehaviour {
    public int score;
    public GUIText distance;
    private Coroutine scoreCoroutine;
    void Start () {
        score = 0;
        scoreCoroutine = StartCoroutine(updateScoreManager(1f, 1));
    }
    IEnumerator updateScoreManager(float totalTime, int amount) {
        while(true) {
            score += amount; 
            distance.text = score.ToString();
            yield return new WaitForSeconds (totalTime);
        }
    }
    // example of ending game
    void EndGame() {
        StopCoroutine(scoreCoroutine);
        scoreCoroutine = null;
    }
}

这可能看起来很奇怪(为什么我要使用无限循环)?但这就是Coroutines的美妙之处,您可以这样写代码,因为yield语句允许您从代码中返回,然后返回到同一位置。通常while循环会导致游戏崩溃,但yield语句让我们创建一个时间while循环!

希望这能有所帮助!

我可以在您的代码中看到一些小故障。让我们先报道一下。

  • 您正在Update中调用Coroutine,延迟时间为1秒。这意味着您的Coroutine每秒执行30或60次
  • 您也在Update中分配文本。这可能是它刷新文本的原因(对此不确定)
  • 在您的Coroutine中,您的延迟(即WaitForSeconds)在这里没有任何用处,因为在那行代码之后什么都没有发生

我正在修改你的确切代码,这样你就可以理解你想要的也可以通过这个实现:)

public class scoremanager : MonoBehaviour {
    public int score;
    public GUIText distance;
    public bool isGameOver = false;
    void Start () {
        score = 0;
        StartCoroutine(updateScoreManager(1f, 1));
    }
    void Update () {
    }
    IEnumerator updateScoreManager(float totalTime, int amount) {
        while(!isGameOver){
            score += amount; 
            distance.text = score.ToString();
            yield return new WaitForSeconds (totalTime);
        }
    }
}

有什么变化。。。

  • Update中没有代码
  • 只调用Coroutine一次
  • Coroutine中,它同时更改scoredistance,每totalTime秒更改一次。直到isGameOver标志为false。游戏结束后,只需将其设为true即可

我想问题的简单解决方案是InvokeRepeating

//Invokes the method methodName in time seconds, then repeatedly every repeatRate seconds.
public void InvokeRepeating(string methodName, float time, float repeatRate);

所以你的转换代码可能是

公共类记分管理器:MonoBehavior{

public int score;
public GUIText distance;
void Start () {
   InvokeRepeating("updateScoreManager",1f,1f);
}
void Update () {
    distance.text = score.ToString();
}
void updateScoreManager() {
    score += 1; 
}

问题是GUIText中没有显示任何内容,所以我不知道它工作于

会发生什么?它总是零还是什么都不显示?如果没有-检查坐标、图层等,以确保正确定位。参考http://docs.unity3d.com/Manual/class-GUIText.html

游戏结束后,我该如何停止计数?

在比赛结束时使用StopCoroutine(updateScoreManager),不要忘记将分数设置为零。

实际上是说你的代码设计不好。实现状态观察者组件模式将非常好。使用state,您可以实现游戏状态,如game、GameOver。使用Observer,您可以通知您的分数组件。对于组件,您可以通过将分数逻辑放置到分数组件来服务于单一责任原则。

至少考虑单独的开始游戏初始化、更新组件和游戏结束逻辑。

我将跳过关于您正在实现的模式的讲座,因为我不知道您的其余代码是什么样子的,但您的更新问题的根源在于:

IEnumerator updateScoreManager(float totalTime, int amount)
    {
        score += amount;
        yield return new WaitForSeconds(totalTime);
    }

在实践中,当我遇到这类问题时,我会将失败的逻辑与源应用程序分离,以帮助减少噪声量。

因此,当我对你的算法进行原型化时(下面的代码),结果是分数总是零,因为StartCoroutine应该在调用.Update()时使用updateScoreManager的返回值来进行更新。

如果我的原型设计似乎与您尝试实现此代码的方式相匹配,那么我可以稍后发布如何修复此问题。

但基本上,不是返回IEnumerator,而是返回一个更新分数的int,这可能会让你克服这个问题。

除非你能描述代码中其他地方需要IE分子的用例?

执行原型:

class Program
{
    static void Main(string[] args)
    {
        Ans34612672 Ans34612672 = new Ans34612672();
        Ans34612672.Execute();
        Console.ReadKey();
    }
}

原型包装类:

public class Ans34612672
{
    public Ans34612672()
    {
    }
    public bool Execute()
    {
        bool retValue = false;
        scoremanager Manager = new scoremanager();
        Manager.Start();
        while(Manager.score < 20)
        {
            Manager.Update();
        }
        Console.WriteLine(Manager.distance);
        Console.ReadKey();
        return retValue;
    }
}

原型类:

public class scoremanager : MonoBehaviour
{
    public int score;
    public GUIText distance;
    public void Start()
    {
        score = 0;
        distance = new GUIText();
    }
    public void Update()
    {
        IEnumerator UpdateResults = updateScoreManager(1f, 1);
        StartCoroutine(UpdateResults);
        distance.text = score.ToString();
    }
    private void StartCoroutine(IEnumerator enumerator)
    {
        //Implement Logic
    }
    IEnumerator updateScoreManager(float totalTime, int amount)
    {
        score += amount;
        yield return new WaitForSeconds(totalTime);
    }
}
internal class WaitForSeconds
{
    private float totalTime;
    public WaitForSeconds(float totalTime)
    {
        this.totalTime = totalTime;
    }
}
public class GUIText
{
    internal string text;
}
public class MonoBehaviour
{
}