- Home /
Getting parts of functions to execute only the first consecutive frame
Hello,
I'm something of a beginner to programming but not to game development in general. After coding away for some months I feel I'm getting comfortable with it, but there are a few things that I'm still struggling with.
One of these things happen quite often. It is a general problem and has to do with repeated execution of a function over several frames, where I only want a certain aspect of the function to happen on the first execution. An example could be the way the GetButtonDown() function works, where it only returns true the first frame a button is pressed.
If the whole execution of the function happens within a single script, this is generally not a problem. For example, a solution could look like this:
bool firstExecution = true;
void Update() {
if Input.GetButton("Fire1") {
MyFunction();
firstExecution = false;
}
else {
firstExecution = true;
}
}
void MyFunction(){
if (firstExecution){
print("This happens the first frame");
}
else {
print("This happens consecutive frames");
}
}
However, this way of doing it seems to become increasingly complicated and problematic when calling functions from other scripts, and when wanting to have several instances of the same function running for different objects.
Some general guidelines on how to approach these kinds of issues would be much appreciated. Is there a better way of doing it than the above, or do I need to keep setting up booleans like this for each object that could run a given function?
I hope I am making some sense here. :-p
Thanks, Jonatan
Answer by rutter · Oct 11, 2012 at 10:14 AM
Actions which take multiple frames are sort of inherently messy, in my experience. Some developers prefer to avoid them whenever possible, but I don't think that's always possible or reasonable. Sometimes you've just got to bite the bullet and keep things as organized as you can. The method you're using is pretty close to some things I've done.
You might look into coroutines, which are functions that Unity can execute over multiple frames: http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.StartCoroutine.html
Most of the examples have coroutines that wait for X seconds, wait for a WWW download to finish, but you can also just return null to wait until the next frame's update cycle, like so:
void Start()
{
StartCoroutine(TwoFrames());
}
IEnumerator TwoFrames()
{
Debug.Log("called!");
return null;
Debug.Log("next frame");
}
You can have multiple calls to the same coroutine running simultaneously, each with its own local variables and so on. This is good if you want them to behave independently, but can also cause its own mess if you're not careful about it.
Either way, don't forget that you always have the option of putting together custom data structures and helper functions to assist you in keeping this process orderly. The particular needs will vary depending on what you're doing.
Amazing that you can only mark one answer as "correct" considering the multitude of correct answers when you're program$$anonymous$$g... :-p
Anyway, I've been using Coroutines more and more recently for these things. Love them so far.
Answer by aldonaletto · May 12, 2012 at 03:59 PM
I usually do the same thing, but keeping the control inside the function: if the boolean flag is set, the function just returns without doing anything. This way you can call the function without checking any control variable - like this:
void Update() { if (Input.GetButton("Fire1")){ MyFunction(); // let the function control itself } }
bool myFunctionDone = false;
void MyFunction(){ if (myFunctionDone) return; // abort call if already executed // MyFunction code goes here myFunctionDone = true; }
You forgot to put myFunctionDone = true; into the function ;)
Thanks for the answer! I believe though that this is essentially the same thing I wrote at first, except the bool is set inside the function ins$$anonymous$$d of outside. However, the bool is still a member of the entire class, and not a local member of the function. This means you can't call several instances of the function from outside scripts and keep track of their different frame-by-frame progress.
Answer by Jonatan Crafoord · Oct 11, 2012 at 09:35 AM
Trying to answer this question myself... It seems that if you want to do this in one and the same instance of a script, but keep track of the state for several other objects calling one function from outside, you have to include the bool in the function call. For example:
public void MyFunction(bool firstExecution)
{
if (firstExecution)
{
do stuff only first frame;
}
else
{
do stuff only consecutive frames;
}
do stuff that happens both first frame and consecutive frames;
}