- Home /
Using InvokeRepeating in the Update method?
I am trying to use the InvokeRepeating function in the Update method so that if a player comes within 4 units of the object it reduces the players health by 1 instantly and then by 1 every 5 seconds. The problem is that InvokeRepeating ignores my repeat rate and just fires constantly. Here is my code:
void Update () {
var dist = Vector3.Distance(player.position, transform.position);
if (dist < 4)
{
InvokeRepeating("Damage", .0001f, 5.0f);
}
}
And the simple damage class:
void Damage()
{
TakeDamage(1);
}
I think the problem lies with using the InvokeRepeating() inside of the Update() method, but I'm not sure how it would be fixed. Thanks in advance!!
Answer by robertbu · Feb 27, 2014 at 06:35 PM
A good solution for this problem is to make your damage a float. Figure out how much damage the player gets per second. Then your code might be:
if (dist < 4)
{
damage -= perSecondDamage * Time.deltaTime;
}
Or if you still want to call a function you can do:
TakeDamage(perSecondDamage * Time.deltaTime);
If you want a regular interval of damage, a solution is the what I call a timestamp. This code will call TakeDamage() approximately every second. At the top of the file put:
private float timestamp = 0.0f;
Then your code in the Update() loop would be:
if (dist < 4 && Time.time >= timestmap)
{
TakeDamage(1);
timestamp = Time.time + 1.0f;
}
Thanks for your help! This works except for as soon as you get within 4 units it reduces by 3-5 very quickly (like the first 3-5 frames you are in range) and then it works flawlessly by reducing by one every second. I'm not sure what would be causing this as I have no other code besides this.
I edited the answer and change line 4. This will fix the problem but introduce a very $$anonymous$$or discrepancy in the firing ti$$anonymous$$g (like 1/120 of a second).
Answer by DubstepDragon · Feb 27, 2014 at 05:00 PM
The update method is for running repeatedly. Using InvokeRepeating in the update method would be like an update within an update method. InvokeRepeating should always be in the Start or Awake methods.
Thanks for your help! This is what I've gathered from reading about this problem, but I'm not sure how I would go about moving this into the start method since it needs to be activated every time the distance is less than 4 units. Any suggestions?
Well, you can use a coroutine to increment/decrement a value every set amount of time. The Unity documentation on this can be found here.
Another way of doing this would be rewriting your code in a different manner. For instance, ins$$anonymous$$d of having an InvokeRepeating method, you can do this ins$$anonymous$$d:
UPDATE:
void Update () {
var dist = Vector3.Distance(player.position, transform.position);
if (dist < 4)
{
Damage();
}
}
DA$$anonymous$$AGE:
void Damage()
{
TakeDamage(1);
}
However doing that will run the method many times per second. If this is not what you want, you can always check out coroutines, since they do things in a fixed time. If you don't get it, reply and I will rewrite the script for you :D
Hope you understood :D
Thank you so much for your help! I'm sorry to ask again, but I cant seem to understand this properly. I tried this code in the update function:
if (dist < 4)
{
StartCoroutine("Damage");
//InvokeRepeating("Damage", .0001f, 5.0f);
}
And the Damage:
IEnumerator Damage() //Sends amount to the TakeDamage class
{
TakeDamage(1);
yield return new WaitForSeconds(5.0f);
}
It still reduces by 1 every frame! Am I even close to having this right? Thanks again!!
Well, while I was drinking my coffee earlier, I thought of something else :D
I have an idea. You can keep your update method like this:
void Update () {
var dist = Vector3.Distance(player.position, transform.position);
if (dist < 4)
{
DamageTemp();
}
}
Now, this will call the temporary method for damage, which is as follows:
void DamageTemp() {
InvokeRepeating("Damage", .0001f, 5.0f);
}
This will start an InvokeRepeating chain for the method Damage. Now, you can have your damage method and do as follows:
void Damage()
{
TakeDamage(1);
}
So just a quick explanation of all that happened:
You use the update method to check if "dist" is less than 4.
If yes, you run the method DamageTemp().
That method will run the chain that will repeat with the parameters that you set (InvokeRepeating).
The InvokeRepeating method will now fire up the Damage() method, doing whatever you want it to do :D
Hope you learn from this! :D
If you have anything at all, any doubts, questions, feel free to comment here :D I will do my best to provide you with what you want :D
Oh and happy upvote :D
Now you have 15 $$anonymous$$arma yay! xD
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
How do I replace Invoke Repeating to allow a repeat rate change 1 Answer
GUIText not updating score.... 1 Answer
I have no idea why this isn't working 0 Answers