需要我的Android游戏的逻辑

时间:2014-11-08 11:40:39

标签: c# android unity3d unityscript

您好我是Unity游戏引擎的新手,我正在创建一个3D射击游戏。在1级我想在一定时间内射击5个敌人,比如30秒。完成1级后,我想进入2级,我的总敌人数为10,并希望在60秒内杀死它,如果失败则会有游戏结束。我为它编写了一些脚本,它有点作用,但它并不完美,因为在开始第2级后游戏变得缓慢并且在游戏结束后再次重新启动,但没有使用10个敌人的默认值,而是从没有。在比赛结束时到达。我的游戏需要一些想法和良好的逻辑和脚本。这是我的代码。

 public class Status : MonoBehaviour
{

    public static int TotalZombies=5;
    public static float timeLeft=25.0f; 

 // destry this game object.
            Destroy (this.gameObject);
            TotalZombies--;
            }

这是我的另一个脚本,我处理我的等级和时间等。

using UnityEngine;
using System.Collections;

public class Generate : MonoBehaviour {
    public GUIText Zombiesobject;
    public string zombiesscore;
    public GUIText countdown;
    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        zombiesscore = "Zombies Left: " + Status.TotalZombies.ToString ();
        Zombiesobject.text = (zombiesscore);

        Status.timeLeft -= Time.deltaTime;
        if (Status.timeLeft <= 0.0f && Status.TotalZombies > 0) 
        {
            countdown.text = "Game Over";
            Application.LoadLevel(Application.loadedLevel);
} 
        else if (Status.timeLeft <= 10.0f && Status.TotalZombies > 0) 
        {
            countdown.text = "Time left = " + (int)Status.timeLeft + " seconds" + "  \n  You are running out of time!";
        } 
        else if (Status.timeLeft > 0.0f && Status.TotalZombies <= 0) {
                countdown.text = "You win!";
                Application.LoadLevel("level 2");
                Status.TotalZombies=10;
                Status.timeLeft=59.0f;
        }
        else
        {
            countdown.text = "Time left = " + (int)Status.timeLeft + " seconds";
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您的问题是您使用static个变量。 static与全局变量完全相同。唯一的区别是您需要通过类名访问它们。

那究竟是什么意思呢?加载游戏时,加载类本身时,会创建并初始化静态变量。在您的情况下,TotalZombies设置为5timeLeft设置为25f

但是只要您的游戏运行,这些变量就会持续存在并且永远不会重新初始化。即使您执行Application.LoadLevel这些变量及其值仍然存在。

这意味着如果您更改这些变量,并重新加载您的级别TotalZombiestimeLeft仍然有其最后的值。

因此,我鼓励永远不要使用static变量。他们很容易引入难以发现的错误。让我们假设一个简单的代码修复。

您还需要为Start()方法添加初始化。例如,在您添加的Status课程中。

void Start() {
    TotalZombies = 5;
    timeLeft     = 25.0f;
}

在你的情况下它可以完全解决问题,但你也可以说这只是偶然或运气。

在Unity中,不存在调用Start()的订单。例如,在加载场景时,Start类中的Generate方法首先会被调用。如果您在Status.TotalZombies中使用Status.timeleftStart来初始化Generate中的某些内容,那么您的初始化错误仍然存​​在错误,因为它使用了上一次运行中的变量。问题是Unity有时可能先在Status.Start()之前执行Generate.Start(),有时反过来。这将导致仅sometimes发生的错误并且非常难以调试。

如果你知道上述内容,你也可以在Awake方法中进行初始化。因为Awake方法将在任何Start方法之前调用。所以这将是一个更好的解决方案。

但是还存在其他问题。例如,让我们查看您的Generate.Update()方法。例如,您可以在Status.timeLeft -= Time.deltaTime;方法中直接执行Update。但是,如果您的游戏中有多个GameObjects具有Generate组件,则表示timeLeft会在一个帧中多次减少Generate。如果您有两个Start组件,则意味着您的时间会快两倍。

因此,即使将初始化放入Awakestatic也可以修复一些错误,但您仍然遇到static s

的不同问题

这就是为什么我鼓励根本不使用timeLeft的原因。那你怎么解决这个问题呢?您应该创建类的属性,而不是静态。最重要的是,您应该只能从您自己的类中设置所有属性。这也对其他代码产生影响。例如,您无法再从Generate缩小timeLeft属性。这听起来像是一个缺点,但它会强迫您考虑如何正确地更改timeLeft。在您的情况下,您并不希望任何地方的任何课程都可以更改Status。这个时间应该不断减少,多次减少它只是一个错误。结果是。您的timeLeft课程应该只更改Update中的TotalZombiesIncrementTotalZombies也是如此。最好只使用DecrementTotalZombiesStatus.TotalZombies++等方法而不是Status等方法。例如,您的public class Status : MonoBehaviour { public int TotalZombies { get; private set; } public float TimeLeft { get; private set; } void Awake() { this.TotalZombies = 5; this.TimeLeft = 25f; } void Update() { this.TimeLeft -= Time.deltaTime; } public void IncreaseTotalZombies() { this.TotalZombies++; } public void DecreaseTotalZombies() { if ( this.TotalZombies <= 0 ) { throw new ApplicationException("Cannot decrease TotalZombies. Already 0. Possible Bug in your code."); } this.TotalZombies--; } } 类现在应该看起来像

IncreaseTotalZombies

现在DecreaseTotalZombiesMaxTotalZombies听起来有点开销,但您可以在这里进行大量额外检查。例如,检查计数器是否永远不会小于零。因为当它发生时,你的代码中有一个错误。例如,将您的TotalZombies意外地增加两个,或者将其减少两个,依此类推。您还可以实现status.IncreaTotalZombies(); status.IncreaTotalZombies(); 属性,以确保您永远不会获得更多定义的僵尸。如果发生这种情况,它会抛出一个Exception,直接将代码指向你的代码。

识别错误也更容易。因为连续两次增加它看起来是错误的。

Status.TotalZombies += 2;

以下代码可以恰到好处

Status.TotalZombies

但是,如果您执行上述更改,您将看到当前的Status不再有效。您还必须更改如何获取Status课程的实例。为此,我们假设您在Unity中创建名为Generate的GameObject。然后在private Status status; void Awake() { this.status = GameObject.Find("Status").GetComponent<Status>(); } 课程中添加以下内容。

Status.TotalZombies++

现在,您可以使用status.IncreaseTotalZombies()替换status.TimeLeft等。如果您只想获取值,您仍然可以编写status.TimeLeft -= Time.deltaTime,但设置值Status现在会抛出错误。并且您不再需要设置它,因为这是Update类已在其Generate方法中处理的行为。

现在,在你的Application.LoadLevel("level 2"); Status.TotalZombies=10; Status.timeLeft=59.0f; 课程中添加了这样的代码。

Application.LoadLevel()

这没有按预期工作。因为当你调用Status.TotalZombies=10; Status.timeLeft=59.0f; Application.LoadLevel("level 2"); 时,你的新场景会被调用,而它背后的线条从未被调用过。你可以解决这个问题,即改变订单。

static

因为您的状态Status值通过加载持续存在。但整个方法仍然不是很好。问题是你在代码中硬编码值。而且你似乎想要每个关卡都有不同数量的僵尸和时间。如果您需要,可以将属性添加到初始化变量的Status类中,并且可以通过Unity IDE设置这些变量。例如,将以下属性添加到public int _StartZombies = 5; public float _StartTime = 25f; 类。

Status

如果您现在在IDE中将其添加到Start Zombies课程,则两个TextBox会显示为Start Time5。在此框中,您现在可以输入您的关卡应该有多少个僵尸或开始时间。这些值的默认值为25Awake。但是这些值并没有适用于加载你的等级。要在加载关卡时应用这些值,请将void Awake() { this.TotalZombies = this._StartZombies; this.TimeLeft = this._StartTime; } 方法更改为。

this.TotalZombies

现在this.TimeLeftApplication.LoadLevel("SomeLevel"); 始终获取您在IDE中配置的值。你现在唯一需要做的就是写作。

[System.Serializable]
public class LoadLevelData {
    public float  TimeLeft;
    public string LoadLevel;
}

您只需通过IDE配置僵尸的数量和时间!它还意味着您现在拥有可重用的组件。并配置它所属的东西!


您还描述了加载新级别需要不同的条件。例如,如果用户能够在特定时间内杀死所有僵尸,则他直接跳到3级而不是2级,依此类推。那么如何在不创建大量特殊类的情况下添加它呢?

首先,你需要一个只保存数据的类。在您的情况下,您需要一个特定的时间和一个定义哪个级别被加载。所以你可以写这样的东西。

Status

但是在我看来逻辑属于public LoadLevelData[] _NextLevels; 类,所以你现在要做的是将以下内容添加到这个类中。

Size

只要将其添加到代码中即可。在Unity IDE中,您将看到&#34; Next Levels&#34;使用&#34;光标&#34;。您现在可以展开此光标,并显示Element 0字段。您现在可以将2写入其中,它会为您提供Element 1LoadNextLevel。因此,Unity使您能够创建对象数组,并且您可以使用所需的任何值从IDE创建任意数量的条目!

现在你可以用这种方式编写public void LoadNextLevel() { foreach ( var level in this._NextLevels ) { if ( level.TimeLeft > this.TimeLeft ) { Application.LoadLevel(level.LoadLevel); } } } 方法了。

Element 0:
    Time Left  -> 20
    Next Level -> "Level 3"

Element 1:
    Time Left -> 10
    Next Level -> "Level 2"

现在您可以在Unity IDE中进行配置

status.LoadNextLevel()

您只需在游戏结束时致电{{1}}。您可以从IDE配置所有内容。另请注意。填充_NextLevel数组的顺序非常重要。在这种情况下&#34;剩下的时间&#34; - &GT; 20必须在&#34; 10&#34;之前。

相关问题