销毁确切对象

时间:2020-03-06 10:37:48

标签: c# unity3d

我正在创建一个小型2D游戏,您需要在其中生存。每棵树都有其自己的强度=5。当玩家碰撞并按下鼠标左键时,强度为-1,玩家木材状态为+1。当树的强度等于或小于0时​​,树将被破坏。这是我的代码:(问题在代码后面)

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Stats: MonoBehaviour
{
    //Player Stats
    public float hp = 100;
    public float wood = 0;

    //Tree stats
    public float treeLogStrenth = 5;

    //Text
    public Text woodText;

    void Start ()
    {
        woodText.text = "0";
    }

    void Update ()
    {
        woodText.text = wood.ToString();

        if (treeLogStrenth <= 0)
        {
            Destroy(GetComponent<PlayerCollisions>().;
        }
    }
}

这是另一个代码:

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

public class PlayerCollisions: MonoBehaviour
{
    public void OnCollisionStay2D (Collision2D collisionInfo)
    {
        if (collisionInfo.gameObject.tag == "Tree" && Input.GetMouseButtonDown(0))
        {
            string treeName = collisionInfo.gameObject.name;
            GetComponent<Stats>().wood += 1;
            GetComponent<Stats>().treeLogStrenth -= 1;
        }
    }
}

我的问题:如何像制作一个简单的代码一样,而不是一直为每棵树都创建另一个游戏对象并销毁它,而不是一直这样做。请帮助(最新版本)

1 个答案:

答案 0 :(得分:0)

所以要清理一下:Stats应该附加在播放器上,对吗?

您不应该在Update的每一帧中都做事,而应该像事件驱动一样

public class Stats : MonoBehaviour
{
    // You should never allow your stats to be set via public fields
    [SerializeField] private float hp = 100;
    [SerializeField] private float wood = 0;

    // if you need to read them from somewhere else you can use read-only properties
    public float HP => hp;
    public float Wood => wood;

    [SerializeField] private Text woodText;

    private void Start ()
    {
        woodText.text = "0";
    }

    public void AddWood(int amount)
    {
        wood += amount;
        woodText.text = wood.ToString();
    }
}

然后,每棵树都应该附加自己的组件实例,例如

public class Tree : MonoBehaviour
{
    [SerializeField] private float treeLogStrenth = 5;

    public void HandleClick(Stats playerStats)
    {
        // if this tree has wood left add it to the player stats
        if(treeLogStrength > 0)
        {
            playerStats.AddWood(1); 
            treeLogStrenth -= 1;
        }

        // destroy this tree when no wood left
        if (treeLogStrenth <= 0)
        {
            Destroy(gameObject);
        }
    }
}

,最后也连接到播放器

public class PlayerCollisions: MonoBehaviour
{
    // better already reference this via the Inspector
    [SerializeField] private Stats stats;

    // will store the currently collided tree in order to reuse it
    private Tree currentlyCollidedTree;

    // as fallback initialize it on runtime
    private void Awake()
    {
        if(!stats) stats = GetComponent<Stats>();
    }

    private void OnCollisionStay2D(Collision2D collisionInfo)
    {
        if (collisionInfo.gameObject.CompareTag("Tree") && Input.GetMouseButtonDown(0))
        {
            // Get the Tree component of the tree object you are currently colliding with
            // but only once and store the reference in order to reuse it
            if(!currentlyCollidedTree) currentlyCollidedTree= collisionInfo.gameObject.GetComponent<Tree>();

            // tell the tree to handle a click and pass in your stats reference
            currentlyCollidedTree.HandleClick(stats);
        }
    }

    // reset the currentlyCollidedTree field when not colliding anymore
    private void OnCollisionExit2D()
    {
        currentlyCollidedTree = null;
    }
}

是的,有一种替代方法,不是每棵树都需要自己的组件实例,但我建议不要实际使用它!

您可以让玩家记住他已经点击过的那棵树

public class PlayerCollisions: MonoBehaviour
{
    // better already reference this via the Inspector
    [SerializeField] private Stats stats;

    // will store all trees we ever clicked on in relation to the according available wood
    private Dictionary<GameObject, int> encounteredTrees = new Dictionary<GameObject, int>();

    // as fallback initialize it on runtime
    private void Awake()
    {
        if(!stats) stats = GetComponent<Stats>();
    }

    private void OnCollisionStay2D(Collision2D collisionInfo)
    {
        if (collisionInfo.gameObject.CompareTag("Tree") && Input.GetMouseButtonDown(0))
        {
            // did we work on this tree before?
            if(encounteredTrees.Contains(collisionInfo.gameObject))
            {
                // if so gain one wood and remove one from this tree
                stats.AddWood(1);
                encounteredTrees[collisionInfo.gameObject] -= 1;
                // destroy the tree if no wood available and remove it from the dictionary
                if(encounteredTrees[collisionInfo.gameObject] <= 0)
                {
                    encounteredTrees.RemoveKey(collisionInfo.gameObject);
                    Destroy(collisionInfo.gameObject);
                }
            }
            else
            {
                // the first time we work this tree gain one wood and add
                // the tree as new entry to the dictionary with 4 wood left
                stats.AddWood(1);
                encounteredTrees.Add(collisionInfo.gameObject, 4);
            }
        }
    }
}

但是,这极大地限制了您,并且您再也无法拥有不同的树木预制件具有不同数量的可用木材...