【问题标题】:Can't figure out what i've done wrong无法弄清楚我做错了什么
【发布时间】:2020-04-04 13:26:56
【问题描述】:

我是编程新手,目前正在尝试在 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++;
                 }
        }  
}

【问题讨论】:

  • 嗨,在递增之前是否已蒸发初始化?代码路径是否执行? ("is one of the if's before true") 你有什么例外吗?
  • 请注意,问题标题应描述您遇到的问题。 “无法弄清楚我做错了什么”没有说明这个问题是关于什么的。
  • 初始化为0,代码执行没有任何问题。
  • 约翰,谢谢你的建议,这是我在这个网站上的第一篇文章。
  • 我看不出代码有什么问题,除了它可能没有运行。如果添加 Debug.Log("代码运行良好!"); if 语句中的行是否按您的预期显示?

标签: c# unity3d


【解决方案1】:

我不太确定您试图在此脚本中获得什么行为。如果 Evaporated 是某种得分的“全局计数器”,则需要将其编写为不同的,而不是存储在此游戏对象的脚本中。 它可能与您的 gameObject.SetActive(false) 有关,它将停用您的对象,因此实际上它也会禁用与其连接的脚本(尤其是这个。SetActive documentation)并将它们从给定的 Update() 中删除gameObject(所以给定敌人。如果场景中有 4 个 Enemy 对象,实际上您有该脚本的 4 个实例,每个实例都有自己的 Evaporated 变量)

【讨论】:

    【解决方案2】:

    您为什么不将 void OnCollisionEnter(Collision CollisionInfo) 移动到您的 Enemy scipt 中?我认为Enemy 现在应该与任何东西碰撞,而不是某些外部脚本。

    您也可以在检测碰撞时使用标签而不是名称。

    另外,gameObject.SetActive(false) - 如果您将游戏对象设置为禁用,除非您再次将其设置为活动,否则脚本中不会发生任何其他事情。它例如取消所有协程。我会说,游戏对象只是“睡觉”。它没有被破坏——你仍然可以在你的层次结构窗口中看到它——但它不能做任何事情。 (顺便说一句,在这种情况下,您将 EnemyEvaporate gameObject 设置为禁用,而不是 Enemy gameObject。)

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

    现在,蒸发。如果你想计算有多少敌人蒸发了(我想,看看Evaporated++;)你应该有一些外部对象来计算它。我现在可以提出的最简单的方法是创建一个带有EvaporationCounter : MonoBehaviour 脚本的游戏对象。您还可以使用单例模式来确保只有一个此类对象。

    public class EvaporationCounter : MonoBehaviour
    {
        private int evaporates;
    
        public int Evaporates {
            get { return evaporates; }
            private set
            {
                if (value >= 0) evaporates = value;
            }
        }
    
        public void AddEvaporation()
        {
            Evaporates++;
        }
    }
    

    你的 Enemy 类可能如下所示:

    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));
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多