无法弄清楚我做错了什么

时间:2020-04-04 13:26:56

标签: c# unity3d

我是编程新手,目前正在尝试在Unity中做一个简单的游戏。

该代码使某些东西在碰到地面时消失了,并且效果很好,但是Unity Inspector中的“ Evaporated”变量没有更新。当有物体接触地面时,蒸发量应该增加,但仍保持在0。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class EnemyEvaporate : MonoBehaviour
{
    public GameObject Enemy;
    public int Evaporated;
    void OnCollisionEnter(Collision CollisionInfo)
        { 
             if (CollisionInfo.gameObject.name == "Map" || CollisionInfo.gameObject.name == "Player")
                 {
                     Thread.Sleep(15);
                     gameObject.SetActive(false);
                     Evaporated++;
                 }
        }  
}

2 个答案:

答案 0 :(得分:0)

我不太确定您要在此脚本中尝试执行的操作。如果“蒸发”是某种分数的“全局计数器”,则需要用不同的方式编写它,而不是将其存储在此gameObject的脚本中。 它可能与您的gameObject.SetActive(false)有关,后者将停用您的对象,因此实际上,它还将同时禁用与之关联的脚本(尤其是此SetActive documentation)并将脚本从Update()中删除。给定一个gameObject(给定敌人)。如果场景中有4个敌人对象,那么实际上您有4个此脚本实例,每个实例都有自己的Evaporated变量)

答案 1 :(得分:0)

您为什么不将空白OnCollisionEnter(Collision CollisionInfo)移到Enemy呢?我认为Enemy现在应该与任何东西(而不是某些外部脚本)发生冲突。

检测冲突时,也可以使用标签代替名称。

此外,gameObject.SetActive(false)-如果将gameObject设置为Disabled,除非再次将其设置为active,否则脚本中不会发生其他事情。例如取消所有协程。我想说,gameObject只是在“睡觉”。它没有被销毁-您仍然可以在“层次结构”窗口中看到它-但它无能为力。 (顺便说一句,在这种情况下,您将EnemyEvaporate gameObject设置为禁用,而不是Enemy gameObject。)

此外,您可以使用Coroutine代替Thread.Sleep(15)。在Unity中,使用协程比使用线程更常见。

现在,蒸发。如果要计算蒸发出多少个敌人(我想看一下Evaporated++;),则应该有一些外部对象来对其进行计数。我现在建议的最简单方法是创建一个附加了EvaporationCounter : MonoBehaviour脚本的GameObject。您还可以使用Singleton模式来确保只有一个这种类型的对象。

public class EvaporationCounter : MonoBehaviour
{
    private int evaporates;

    public int Evaporates {
        get { return evaporates; }
        private set
        {
            if (value >= 0) evaporates = value;
        }
    }

    public void AddEvaporation()
    {
        Evaporates++;
    }
}

您的敌人职业可能看起来像:

public class Enemy : MonoBehaviour
{
    private IEnumerator coroutine;

    private EvaporationCounter evaporationCounter;

    private void Start()
    {
        evaporationCounter = FindObjectOfType<EvaporationCounter>();
    }

    private IEnumerator WaitAndSetInactive(float waitTime)
    {
        yield return new WaitForSeconds(waitTime);

        gameObject.SetActive(false);
    }

    private void OnCollisionEnter(Collision CollisionInfo)
    {
        if (!CollisionInfo.gameObject.CompareTag("Map") && !CollisionInfo.gameObject.CompareTag("Player")) return;
        if (evaporationCounter != null)
            evaporationCounter.AddEvaporation();
        StartCoroutine(WaitAndSetInactive(15f));
    }
}

从敌人脚本中调用evaporationCounter.AddEvaporation()并不是最好的解决方案,因为它不适用于Dependency Inversion principle,但我想说这对于从Unity开始是有好处的。