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 Answer 1

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\$
3
  • \$\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\$ Jun 17, 2017 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\$ Jun 17, 2017 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\$ Jun 18, 2017 at 0:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .