- Home /
foreach (or for-next loop) not updating local values
Hi
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. thanks
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[i].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);
}
Sorry but I don't understand the question. What do you mean by "not updating local values"? Are you saying that your dist
and t
aren't being set to the right things?
It's also far from clear what the purpose of t
is. It looks completely redundant.
The logging at line 36 is puzzling too - presumably it always tells you that dist
and t
are both zero. You've only just initialised them both to zero.
Answer by wibble82 · Dec 09, 2015 at 01:43 PM
Hi
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:
Instantiate an instance (i.e. copy) of the prefab 'street'
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 :)
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 :)
-Chris
Hi Wibble and Bonfire
Yes, the behaviour is that the next street is using the previous values. I will make the suggested changes to the code, and clean up what isn't needed.
Thanks for your help Sonja
Thank you Chris, the casting of the GameObject worked great. And I'll use your suggestions regarding code tidiness.
If you want to reply to an answer, use the Add Comment button below that answer. You posted two answers. Answers should answer the question. This is not a forum. On a Q&A site there's always one question and answers that should answer the question. For everything else you should use comments.
However keep in $$anonymous$$d that UnityAnswers is not for discussions, that's what the UnityForum is made for. You might want to have a look at the FAQs of UnityAnswers.
Your answer
Follow this Question
Related Questions
Converting foreach touch into for. 1 Answer
For loop does not loop C# 2 Answers
C# For loop in button to set gameObjects in array to active 1 Answer
ScrollableList best way to implement 0 Answers
Foreach Statement Random Sequence/Order? 3 Answers