Getting a GameObject's position in prefab script

Hi guys,
I have a prefab (gets instantiated at run-time) which contains a script. In this script I declare a GameObject water (to reference an object already instantiated in my hierarchy) and in start() I do:

water = GameObject.Find("Water");

Another script constantly changes the water-object’s Y-position and indeed when I run I can see it changing. However, when I access the water-object’s Y-position from my prefab script it constantly gives me only the initial Y-position of water even though it’s actually changing. How do I do it so that I’m retrieving the current Y-value of water?

transform.position returns the current position so you are doing that correctly. It sounds like the object you are moving is not the same as the ‘Water’ object you are referencing in your scripts.

You can easily check if this is the case. Make the water reference a public variable in your script so that you can click on that object and see what it is via the inspector at runtime.

Ok, so I did that and the referenced object is indeed the water-object. Could it be something else that’s causing the problem?

You’re not trying to cache a reference to the position vector are you?

That doesn’t work, it will create a copy and act exactly as you describe. Vectors can’t be referenced. You have to fetch it directly from the gameobject every time.

Can you give an example of this?
In the water-object’s script I use a coroutine to raise the water level gradually:

void Update()
    {
        StartCoroutine("Rise");
    }

    IEnumerator Rise()
    {
        for (float f = 1.7f; f <= 3.0f; f += 0.001f)
        {
            transform.position = new Vector3(transform.position.x, f, transform.position.z);
            yield return null;
        }
    }

In the prefab’s script, I’m accessing the new water levels like so:

...
public GameObject water;
...
void Start()
{
   ...
   water = GameObject.Find("Water");
   ...
}
void Update()
{
    for (int i = 0; i < myFood.Count; i++)
    {
        if(water != null)
        {
            Debug.Log(water.transform.position.y);
            myFood[i].transform.position = new Vector3(myFood[i].transform.position.x, water.transform.position.y, myFood[i].transform.position.z);
        }          
    }
}

First guess is that you have more than one GameObject in your scene named “Water” and the one you found is not the one you’re moving. Do this:

Debug.Log("this is my water", water);

And click on the message in the console to highlight the water GameObject in the hierarchy.

Also - your water movement code is kicking off a new coroutine every frame. Which might be part of the issue as well.

So, as @KelsoMRK pointed out, the problem was indeed that I was starting the coroutine in Update(). Moving it to Start() solved the problem.

1 Like

Optionally - just make Start the coroutine itself :slight_smile:

Also, don’t use GameObject.Find - @KelsoMRK pointed out one of the potential issues with it in this case. This seems like the time for a singleton, or perhaps FindWithTag.

FindWithTag is now being used instead :slight_smile:

Any benefits to that?

Just slightly cleaner code.

Is that a C# feature? I thought only JavaScript and Boo could do that.

No - Start can be a coroutine by nature of Unity’s API. Has nothing to do with which language you use.

This works fine

IEnumerator Start()
{
    while (true)
    {
        yield return null;
    }
}