0
\$\begingroup\$

I have an enemy game object and an item game object.

Enemies have an ItemDrops script attached. Items have a DisplayItemLabel script attached.

Attached to each enemy:

public class ItemDrops : MonoBehaviour 
{
    public Transform itemPrefab;
    private EnemyHealth enemyHealth;

    private float originToGroundDistance;
    private Vector3 offset;

    private bool itemDropped;
    private bool numberGenerated;
    private float randomNumber;

    private ItemData itemData;
    public string nameOfDroppedItem;

    void Start()
    {
        enemyHealth = GetComponent<EnemyHealth>();

        itemData = GameObject.Find("Item Manager").GetComponent<ItemData>();
    }

    void Update()
    {
        //Initialized in Update instead of Start because enemy floats to 1.083333 on the Y-axis after some time after Start
        originToGroundDistance = transform.position.y - 0.25f;
        offset = new Vector3(0f, originToGroundDistance, 0f);

        if (enemyHealth.isDead && !itemDropped)
        {
            if (!numberGenerated)
            {
                RandomNumberGenerator();

                //Debug.Log(randomNumber);

                if (randomNumber < 1)
                {
                    SpawnItem(itemData.coin);
                }
            }
        }
    }

    private void RandomNumberGenerator()
    {
        numberGenerated = true;

        randomNumber = Random.value;
    }

    private void SpawnItem(Item item)
    {
        itemDropped = true;
        nameOfDroppedItem = item.itemName;

        Instantiate(itemPrefab, transform.position - offset, Quaternion.identity);
    }
}

Attached to each item:

public class DisplayItemLabel : MonoBehaviour 
{
    private GameObject itemLabel;
    private Text itemNameText;

    void Start()
    {

        itemLabel = transform.Find("Canvas/Item Label").gameObject;
        itemNameText = itemLabel.GetComponentInChildren<Text>();

        itemNameText.text = "Item Name";

        itemLabel.SetActive(false);
    }

    void Update()
    {
        ClampLabelToItem();
    }

    private void ClampLabelToItem()
    {
        Vector3 offset = new Vector3(0f, 16f, 0f);

        Vector3 desiredPosition = Camera.main.WorldToScreenPoint(transform.position) + offset;
        itemLabel.transform.position = desiredPosition;

        itemLabel.SetActive(true);
    }
}

Item is not a child of enemy for multiple reasons I can think of. One is that enemies are destroyed when they are killed. With that said, how do I get the item to know who dropped it or get the enemy to know which item it dropped? MY GOAL is to get itemNameText.text = "Item Name"; to say something like itemNameText.text = itemDrops.NameOfDroppedItem; but I can't use GameObject.FindGameObjectWithTag("Enemy").GetComponent<ItemDrops>(); because it won't always grab the correct enemy and thus the correct ItemDrops script. I also can't set DisplayItemLabel.itemNameText.text = nameOfDroppedItem in the SpawnItem function because it wouldn't know which item's DisplayItemLabel script to get.

So clearly, I'm having issues with references. What should I do?

\$\endgroup\$
1
\$\begingroup\$

You see where you have this line:

Instantiate(itemPrefab, transform.position - offset, Quaternion.identity);

Instantiate returns an object, that being the object created. Know what you can do with it?

GameObject drop = Instantiate(itemPrefab, transform.position - offset, Quaternion.identity);
DisplayItemLabel label = drop.GetComponent<DisplayItemLabel>();
label.itemNameText.text = this.gameObject.name;

Ta da. You can pass data from the enemy script to the spawned object without having to rely on the persistence of the enemy.

\$\endgroup\$
  • \$\begingroup\$ This is exactly the kind of thing I was looking for. For some weird reason though I'm still getting a NullReferenceException. I can do itemNameText.text = "text"; from the DisplayItemLabel script, but when I do label.itemNameText.text = "text"; from SpawnItem() in the ItemDrops script, I get this exception. \$\endgroup\$ – embracethefuture Jun 17 '17 at 20:09
  • \$\begingroup\$ When I debug label, I get the DisplayItemLabel script. When I debug label.itemNameText, I get Null. itemNameText is public too. Not sure what could be wrong. \$\endgroup\$ – embracethefuture Jun 17 '17 at 20:20
  • \$\begingroup\$ @embracethefuture It's because the Start() method of that script hasn't run yet. That said, you can assign the value in the prefab directly, you don't need transform.Find("Canvas/Item Label") at all. Alternatively, you can do that same Find after the instantiate but before you set the text. \$\endgroup\$ – Draco18s Jun 18 '17 at 0:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.