foreach (or for-next loop) not updating local values


the problem I’m having is known, but I haven’t been able to find a suitable answer that actually works. For context, I am procedurally generating a city that for the moment has gates at the edges and town squares somewhere in the middle of the city.

What I would like to do is instantiate a street linking the two points. In the code below, everything works fine with the exception of the street’s length (distance), which is correct but for the previous street GameObject. In other posts regarding this, people have suggested using a proxy variable: in my case I’m using “t” against the final variable “dist”. But alas, still no luck. Although, on the plus side, my knowledge of c# closure issues using lamba has improved.

Any suggestions are appreciated.

ps. I’ve removed the Debug statements to help the code be more readable.

// ----- the method's code ---- //
    void PlazaToExitStreets()
            GameObject[] SqStart;
            SqStart = GameObject.FindGameObjectsWithTag("squareCent");
            GameObject[] ExitEnds;
            ExitEnds = GameObject.FindGameObjectsWithTag("gate");
            Debug.Log("the number of gates is " + ExitEnds.Length);
            //foreach (GameObject exitEnd in ExitEnds) // this is the foreach version
            for(int i = 0;i<ExitEnds.Length;i++)
                //choose a (psuedo)random square and gate as end points
                int sqRand = Random.Range(0, SqStart.Length);
                //get the two points (gate & town square/plaza)
                Vector3 exitPos = ExitEnds*.transform.position;*

Vector3 startPos = SqStart[sqRand].transform.position;

//figure out the middle point between the two
Vector3 streetCent = Vector3.Lerp(exitPos, startPos, 0.5f);

//calc the angle between the two so the street’s “y” rotation is correct
Vector3 relPos = startPos - streetCent;
Quaternion rot = Quaternion.LookRotation(relPos);
Quaternion offSetAngle = Quaternion.Euler(0, 90, 0);
Quaternion dir = rot * offSetAngle;

//get the distance between the two points to set the street’s length
Vector3 heading = startPos - exitPos;
float dist = 0; //setting local variable
float t = 0; //setting local variable in hopes that it will “cycle” the values
Debug.Log("1 so dist = " + dist + " and t = " + t);
t = heading.magnitude * 0.1f;
dist = t;

// create a street
Instantiate(street, streetCent, dir);

//set the street’s length
street.transform.localScale = new Vector3(dist, 1, 0.1f);



There’s some odd bits of code there, as mentioned by @Bonfire Boy in his comment. However I think the critical part of your issue is where you instantiate and then set the distance.

Your code basically says:

  1. Instantiate an instance (i.e. copy) of the prefab ‘street’
  2. Set the transform.localScale of the prefab to [dist,1,0.1]

The result of this is that the next iteration around the loop when it instantiates the next street, the prefab will have an updated localScale. This will then be copied into the new street when you instantiate.

I would imagine the effect you’re seeing is that each street you spawn has the distance you calculated from the previous iteration.

I’m not sure what you mean by ‘cycle’ the value, or why your debug log is there - maybe you’ve just got a bit confused along the way :slight_smile:

The critical change to me would be:

 // create a street and store the result. we need to use the cast '(GameObject)', as Instantiate
 // just returns an 'object', and we need to tell the compiler we're expecting a 'GameObject'
 GameObject new_street = (GameObject)Instantiate(street, streetCent, dir);
 //set the newly created street's length
 new_street.transform.localScale = new Vector3(dist, 1, 0.1f);

Here I get the result of Instantiate - the new game object, and then set its local scale.

As an extra tip, as ‘street’ is referring to a prefab, I would strongly recommend you name it as such to avoid confusion. i.e. streetPrefab would be a better name! Clean code = less bugs :slight_smile: