建立统一的评分系统
本文关键字:分系统 建立 | 更新日期: 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
中,它同时更改score
和distance
,每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
{
}