- Home /
Start() being called more than Once?!?
I have a script that controls a score screen in the game. Its has some variables set, a start function where some calculations happen then an OnGUI() to display it all with some menu buttons. The problem I'm having is that Start() is being called like Update(), that is, it's being called continuously. Am I missing something when I say Start only gets called once when the script is first loaded? Or, am I confusing Start() and Awake()?
I have checked to make sure Im not causing the loop myself and that doesn't look to be the case.
{EDIT} Just a quick recap of what's below. Start() is being looped for some unknown reason. The relevant code is below as well as an explanation of the game flow. Using Awake() shows the same recall/looping behavior. The 2 functions in Start().. AccuracyCal() and BonusCal()are not called anywhere else on the script or in other scripts. I need the Click and Clack Brothers of Unity to figure this one out.
First, are you sure Start is called multiple times? Put a Debug.Log inside the Start function. If it is called multiple times then it's very likely that you call it multiple times. Start is a normal function it is only called once by Unity. You can call it manually as often as you like.
If you select a Debug.Log entry in the console it shows a stacktrace so you can see from where it has been called.
Ok, it never gets to the end of start... put an output at the beginning of Start and one on the last line of Start... it never leaves the BonusCal() function. But there is nothing in the function that would cause it to loop. And its only ever used (called once) and that is in Start().
Ok, some edits. I had collapse on. It appears that after it finishes the bonus calculation it recalls Start(). Because I am seeing that debug output on the first line of start increment up but never the last debug line just after BonusCal().
Edit, I was wrong.. it is finishing start and placing the last debug line. It just gets buried in the output. So Start is looping for some reason, back to square 1.
I swear Im not crazy. I thought it might have something to do with the Array but a simple test script ruled that out.
Answer by PAEvenson · Mar 05, 2013 at 03:42 AM
perhaps you are continuously loading that scene over and over....
try adding this to debug:
function OnLevelWasLoaded (level : int) {
print ("Woohoo");
}
That Helped me find it. It was a logic error much earlier in the code. function EndLevel(){
if (levelEnd == true){
levelEnd = false;//added this line to fix it
Application.LoadLevel("sceneScore");
}
I created this based on your suggestion and it worked beautifully.
function OnLevelWasLoaded (level : int) {
switch(level){
case 0:
Debug.Log("Player Object Was Loaded");
break;
case 1:
Debug.Log("$$anonymous$$enu Was Loaded");
break;
case 2:
Debug.Log("Game Screen Loaded");
break;
case 3:
Debug.Log("Score Screen Loaded");
break;
}
}
Elevate your comment to an answer and Ill mark this answered.
Answer by PAEvenson · Mar 04, 2013 at 09:37 PM
Here is the explanation straight from the Unity script reference:
"Start is called just before any of the Update methods is called the first time.
Start is only called once in the lifetime of the behaviour. The difference between Awake and Start is that Start is only called if the script instance is enabled. This allows you to delay any initialization code, until it is really needed. Awake is always called before any Start functions. This allows you to order initialization of scripts.
The Start function is called after all Awake functions on all script instances have been called."
If you have multiple instances of this script on other gameobjects each of those object's Starts will also be called. Maybe this is whats causing it?
I thought that might be the case as well, but that's not what Im seeing. The game starts and calls an empty scene that loads the player script and this script is using DontDestroyOnLoad() method. The script then loads the menu scene. The menu scene just has an empty GameObject with the menu script attached. From here you can select to start the game or up your level.
Once start is pressed a new scene called sceneLevel_1 is called and it runs off of the Enemy script. When the timer reaches 0 a new scene is called, the score scene. The score scene like the menu scene is just an empty GameObject with the score script attached. It will present the player with menu options relevant to the games outcome..ie Continue if Win(sceneLevel) or Go back to $$anonymous$$ain $$anonymous$$enu (scene menu). Everything references the original player script that was created on game start.
In this case the Bonus calculation is the only one that is looping in the Start() function. The Accuracy calculation is also called in Start but it is not looping. See the code posted above.
That makes no sense at all. What you say means that you call your Bonus calculation function somewhere else. A function is called or not. It's not possible that a part executes and another does not unless you get an exception which would ter$$anonymous$$ate the execution at the current point. Do you get any exceptions?
If you use $$anonymous$$onoDevelop, right-click on the function name, in your case "BonusCal" and select "Find references". $$anonymous$$onoDev. is slow like hell, it might take some sec until you see the results. It should give you a list of spots where this function is being used. Check them all
Answer by HunterKrech · Mar 04, 2013 at 09:32 PM
If the object that this script is on is being instantiated then it will run again, but other than that it will only run once. Try Awake() and see if that fixes it.
I tried Awake(), same thing. The script is attached to an empty GameObject I called ScoreGUI and its in an empty scene, ntohing but this script and a camera. Interestingly enough its just the one function that is repeating. Ill post the relevant code below.
var player:scPlayer = null;
var currentLevel: int;
var currentScore: int;
var roundTotal:int;
var accuracy:float;
var bonusPoints:Array;
function Start(){
player = GameObject.FindWithTag("Player").GetComponent(scPlayer); //get player
currentLevel = player.GetPlayerStats("playerLevel");
currentScore = player.GetPlayerStats("playerScore");
accuracy = AccuracyCal(player);
bonusPoints= BonusCal(player,currentLevel,accuracy);
}
function OnGUI(){
GUI.Label(Rect(label1X,label1Y,label1W,label1H), "Level: " + player.GetPlayerStats("playerLevel"));
GUI.Label(Rect(label2X,label2Y,label2W,label2H), "Enemies $$anonymous$$illed: " + player.GetPlayerStats("enemies$$anonymous$$illed"));
GUI.Label(Rect(label3X,label3Y,label3W,label3H), "Clones $$anonymous$$illed: " + player.GetPlayerStats("enemieClones$$anonymous$$illed"));
GUI.Label(Rect(label4X,label4Y,label4W,label4H), "Shots Fired: " + player.GetPlayerStats("numberOfShots"));
GUI.Label(Rect(label5X,label5Y,label5W,label5H), "Shots $$anonymous$$issed: " + player.GetPlayerStats("numberOf$$anonymous$$isses"));
GUI.Label(Rect(label6X,label6Y,label6W,label6H), "Accuracy: " + accuracy +" %" );
GUI.Label(Rect(label7X,label7Y,label7W,label7H), "Round Score: " + player.GetPlayerStats("roundScore"));
GUI.Label(Rect(label8X,label8Y,label8W,label8H), "Accuracy Bonus: " + bonusPoints[0] );
GUI.Label(Rect(label9X,label9Y,label9W,label9H), "Level Bonus: " + bonusPoints[1] );
GUI.Label(Rect(label10X,label10Y,label10W,label10H), "Round Total: " + roundTotal );
$$anonymous$$enuOptions();
}
function AccuracyCal(player:scPlayer){
var miss:float = player.GetPlayerStats("numberOf$$anonymous$$isses");
var numShots:float = player.GetPlayerStats("numberOfShots");
var acc:float = 100 - (miss/numShots) * 100 ;
acc = acc * 100;
var intacc:int = acc;
var correctedAcc:float = intacc/100;
print("accuracy :" + correctedAcc);
return correctedAcc;
}
function BonusCal(player:scPlayer, level:int, acc:float){
var bonus = [0,0];
var accBonus: int = (level*500)*acc / 100;
bonus[0] = accBonus;
var levelBonus:int = (level*200);
bonus[1] = levelBonus;
var rndScore:int = player.GetPlayerStats("roundScore");
roundTotal = rndScore+accBonus+levelBonus;
var newPlayerScore:int = player.GetPlayerStats("playerScore");
print(newPlayerScore);
print(accBonus);
print(levelBonus);
newPlayerScore = newPlayerScore + accBonus + levelBonus;
player.SetPlayerState("playerScore",newPlayerScore);
print(newPlayerScore);
return bonus;
}
What does your $$anonymous$$enuOptions function do? Are you really sure that should be in OnGUI?
$$anonymous$$enuOptions() just controls what menu buttons appear and what they do based on a win or a loss.
function $$anonymous$$enuOptions(){
var winCase = 1000 + (currentLevel * 500);
if (roundTotal > winCase){
var nextLevelButton = GUI.Button(Rect(button1X,button1Y,button1W,button1H),"Next Level");
var menuReturn = GUI.Button(Rect(button2X,button2Y,button2W,button2H),"$$anonymous$$ain $$anonymous$$enu");
}
else{
var clean$$anonymous$$enuReturn = GUI.Button(Rect(button2X,button2Y,button2W,button2H),"$$anonymous$$ain $$anonymous$$enu");
}
if(nextLevelButton){
print("Level Button Pressed, Loading");
Application.LoadLevel("sceneLevel_1");
player.NextRound();
}
if(menuReturn){
print("menu return pressed");
Application.LoadLevel("scene$$anonymous$$enu");
}
if(clean$$anonymous$$enuReturn){
player.PlayerReset();
Application.LoadLevel("scene$$anonymous$$enu");
}
}