Уничтожение точного объекта - PullRequest
0 голосов
/ 06 марта 2020

Я создаю маленькую 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;
        }
    }
}

МОЙ ВОПРОС : Как сделать вместо создания все время другой игровой объект для каждого дерева и уничтожающий его, только как один простой код, который сделает это. пожалуйста, помогите (UNITY NEWES VERSION)

1 Ответ

0 голосов
/ 06 марта 2020

Итак, чтобы прояснить ситуацию: 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);
            }
        }
    }
}

this однако вас сильно ограничивает, и больше невозможно, например, иметь разные сборные заготовки дерева с разным количеством доступной древесины ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...