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 (!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?

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.

• 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. – embracethefuture Jun 17 '17 at 20:09
• 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. – embracethefuture Jun 17 '17 at 20:20
• @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. – Draco18s no longer trusts SE Jun 18 '17 at 0:57