游戏破坏Unity的错误,即使被摧毁,也有太多玩家打破游戏

时间:2018-04-27 03:53:58

标签: c# unity3d

我是一名独立开发人员,在Unity的一个名为Kingdom of Lies的项目上独立工作,我的工作的例子可以在Minds.com的LokisKingdom找到。 (警告:NSFW内容)从开发的最初阶段开始,我已经在这个游戏中长期存在一个错误。通过摧毁玩家并产生一个新玩具来拾取武器。这在大多数情况下都很好,但是如果同时拾取多个武器,它会产生多个玩家。起初这实际上很有趣,因为控制一个小组是有趣的,但如果那个小组开始拿起多个武器,在几秒钟内它就会产生145个玩家,游戏就会停止。你不能移动,你不能退出,甚至不能替换F4,你必须杀死进程才能阻止它。

随着游戏越来越接近完成状态,我再次回过头来解决问题。我设法解决了产生额外球员的问题。我只是创建了一个列表并销毁了第一个之后的所有玩家。但这是最奇怪的部分,无论如何游戏都会破裂。即使没有其他玩家跑来跑去,如果你同时拿起足够多的额外武器,游戏会越来越慢,并最终冻结,你杀了这个过程。在这一点上,我很难过。显然它不是关于屏幕上的对象数量,关于交互本身的一些东西是打破程序的。

以下是相关代码的一些示例。

GUIJar.cs中的

(在Update()中调用)

void HandleMultiplePlayers()
{
    GameObject[] PileOfPlayers;
    PileOfPlayers = GameObject.FindGameObjectsWithTag("User");

    numPlayers = 0;

    if (PileOfPlayers.Length > 0)
    {
        foreach (GameObject thePlayer in PileOfPlayers)
        {
            numPlayers++;
            PlayerPrefs.SetInt("PLAYERPILE", numPlayers);

            if (numPlayers > 1)
            {
                Object.Destroy(thePlayer);
            }
        }
    }
}

稍后在GUIJar.cs

void OnGUI() {

    if (domain == 1)
    {
        GUI.Label(new Rect(10, 10, 100, 20), "Score " + score + " Snowflakes " + enemiesRemaining + " Heads " + heads, customstyle);
    }
    else
    {
        GUI.Label(new Rect(10, 10, 100, 20), "Score " + score + " Remaining " + enemiesRemaining + " Heads " + heads, customstyle);
        GUI.Label(new Rect(10, 70, 100, 20), "Number of Players: " + numPlayers, customstyle);
    }
    }
GunBehavior.cs中的

void OnTriggerStay(Collider other) 
{
    if (PlayerPrefs.GetInt("PLAYERPILE", 0) < 4)
    {
        if (gunType == 0)
        {
            if (SpawningOnce == false)
            {

                if (other.gameObject.tag == "Player")
                {
                    if (Input.GetKeyDown(KeyCode.Tab))
                    {
                        SpawnNewWeapon("Player(gun)", "BatObject", other.gameObject);
                    }

                    if (Input.GetMouseButtonDown(1))
                    {
                        SpawnNewWeapon("Player(gun)", "BatObject", other.gameObject);
                    }
                }

                if (other.gameObject.tag == "Player(knife)")
                {
                    if (Input.GetKeyDown(KeyCode.Tab))
                    {
                        SpawnNewWeapon("Player(gun)", "KnifeObject", other.gameObject);
                    }

                    if (Input.GetMouseButtonDown(1))
                    {
                        SpawnNewWeapon("Player(gun)", "KnifeObject", other.gameObject);
                    }
                    // Process continues for each type of player and item picked up
                }
           }
      }
 }

}

同样在GunBehavior.cs

void SpawnNewWeapon( string pickUpName, string dropName, GameObject theObject)
{
    if (PlayerPrefs.GetInt("PLAYERPILE", 0) < 4)
    {
        SpawningOnce = true;
        Instantiate(Resources.Load("Switch", typeof(GameObject)));
        GUIJar.blood = false;

        GameObject weaponclone;
        weaponclone = Instantiate(Resources.Load(dropName, typeof(GameObject))) as GameObject;
        weaponclone.transform.position = theObject.gameObject.transform.position;

        GameObject clone;
        clone = Instantiate(Resources.Load(pickUpName, typeof(GameObject))) as GameObject;
        clone.transform.position = theObject.gameObject.transform.position;

        Object.Destroy(theObject.transform.parent.gameObject);
        Object.Destroy(this.gameObject);
    }
}

如果您下载并下载游戏,它将包含一个包含所有脚本的文件夹,以防您想要查看Movement.cs,Movement2.cs和Movement3.cs或PlayerBehavior.cs。但除了代码的复杂性之外,我认为它与这个问题无关。相当确定问题的根源在于我刚发布的代码。也许我应该重新制作玩家类是武器之间的转换而不是武器破坏和替换玩家,但所使用的过程非常深深地嵌入代码中并且很难改变。如果可能,我宁愿修复现有代码。

非常感谢任何帮助......

[对不起,如果这是一个不好的问题,这是我第一次问一个。]

1 个答案:

答案 0 :(得分:1)

我解决了这个问题。我所做的是我在武器类本身内部注释了代码,然后将武器切换代码移动到了玩家类中,然后我进入了GUIJar类并做了一个小函数,在bool触发之前等了四分之一秒回到假。然后在玩家类中,当武器开关发生时,玩家调用GUIJar等待函数,将bool触发为true,并且在bool再次为假之前无法获取武器。

这解决了多玩家产卵问题和无限重生武器。这是我游戏中唯一的主要错误,信不信由你。现在经过一些改进和大量的bug测试以确保其正常工作后,当我考虑提交此游戏时,我现在感觉更安全。

[编辑,当然,对于此编辑的迟到感到抱歉:]

在PlayerBehavior.cs中:

void OnTriggerStay(Collider other)
{
    GameObject gui = GameObject.FindWithTag("GUIJar");

    if (Input.GetMouseButtonUp(1) || Input.GetKeyUp(KeyCode.Tab))
    {
        if (other.gameObject.tag == "GunPickup")
        {
            if (gui.GetComponent<GUIJar>().WaitForWeaponSwitch == false)
            {
                gui.GetComponent<GUIJar>().SetWeaponSwitch();

                // Object.Destroy(other.gameObject);
                DropWeapons();
                SpawnReplacementPlayer("Player(gun)", other.gameObject);
            }
            return;
        }

        if (other.gameObject.tag == "ShotgunPickup")
        {
            if (gui.GetComponent<GUIJar>().WaitForWeaponSwitch == false)
            {
                gui.GetComponent<GUIJar>().SetWeaponSwitch();
                //Object.Destroy(other.gameObject);
                DropWeapons();
                SpawnReplacementPlayer("Player(shotgun)", other.gameObject);
            }
            return;
        }

        if (other.gameObject.tag == "GrenadeLauncherPickup")
        {
            if (gui.GetComponent<GUIJar>().WaitForWeaponSwitch == false)
            {
                gui.GetComponent<GUIJar>().SetWeaponSwitch();
                //Object.Destroy(other.gameObject);
                DropWeapons();
                SpawnReplacementPlayer("Player(grenade)", other.gameObject);
            }
            return;
        }

        if (other.gameObject.tag == "BatPickup")
        {
            if (gui.GetComponent<GUIJar>().WaitForWeaponSwitch == false)
            {
                gui.GetComponent<GUIJar>().SetWeaponSwitch();
                //Object.Destroy(other.gameObject);
                DropWeapons();
                SpawnReplacementPlayer("Player", other.gameObject);
            }
            return;
        }

        if (other.gameObject.tag == "KnifePickup")
        {
            if (gui.GetComponent<GUIJar>().WaitForWeaponSwitch == false)
            {
                gui.GetComponent<GUIJar>().SetWeaponSwitch();
                //Object.Destroy(other.gameObject);
                DropWeapons();
                SpawnReplacementPlayer("Player(knife)", other.gameObject);
            }
            return;
        }
    }
}

同样在PlayerBehavior.cs中:

void SpawnReplacementPlayer(string pickUpName, GameObject theObject)
{
        Instantiate(Resources.Load("Switch", typeof(GameObject)));
        GUIJar.blood = false;

        GameObject clone;
        clone = Instantiate(Resources.Load(pickUpName, typeof(GameObject))) as GameObject;
        clone.transform.position = this.gameObject.transform.position;

        Object.Destroy(theObject);
        Object.Destroy(this.gameObject);
}

在GUIJar类中:

IEnumerator WaitToSwitchWeapons(float waitTime)
{
    yield return new WaitForSeconds(waitTime);

    WaitForWeaponSwitch = false;

}

public void SetWeaponSwitch()
{
    if (WaitForWeaponSwitch == false)
    {
        StartCoroutine(WaitToSwitchWeapons(0.25F));
        WaitForWeaponSwitch = true;
    }
}