Damage Over Time problem
I'm in the process of making a sidescrolling shooter sort of game in a fantasy setting. One of my player's abilities is to conjure a flame wall anywhere on the terrain. When an enemy walks across flame wall particle system's prefab's box collider, it sets the bool isOnFire == true in that enemy's script. The enemy script also inherits flameWallDuration, flameWallTimer, flameWallDelay and flameWallDamage from another script. All floats. flameWallDuration is set to 2, both flameWallTimer and flameWallDelay are set to 0.5f, and flameWallDamage is set to 20. This particular enemy's health, monsterOneHealth, is equal to 30. The following is the relevant script:
using UnityEngine;
using System.Collections;
public class MonsterTwoScript : AttackScript
{
public GameObject monsterTwo;
private float monsterTwoHealth = 30;
private bool isOnFire = false;
void Start ()
{
this.flameWallDuration = 2;
this.flameWallTimer = 0.5f;
}
// Update is called once per frame
void Update ()
{
if(monsterTwoHealth <= 0)
{
Destroy(gameObject);
}
Destroy(gameObject, 8);
if(isOnFire == true)
{
this.flameWallDuration -= Time.deltaTime;
if(this.flameWallDuration != 0)
{
this.flameWallTimer -= Time.deltaTime;
if(this.flameWallTimer < 0)
this.flameWallTimer = 0;
if(this.flameWallTimer == 0)
{
this.monsterTwoHealth -= (flameWallDamage/4);
this.flameWallTimer += flameWallDelay;
}
}
if(this.flameWallDuration < 0)
this.flameWallDuration = 0;
if(this.flameWallDuration == 0)
this.isOnFire = false;
if(this.transform.childCount > 0 && isOnFire != false)
{
GameObject fireEffect = this.transform.GetChild(0).gameObject;
fireEffect.particleEmitter.emit = true;
}
}
}
void OnTriggerEnter (Collider other)
{
if(other.gameObject.tag == "FlameWall")
{
isOnFire = true;
}
}
}
The problem is, whenever this enemy catches on fire, it will either not take any damage at all or it will continue to take damage well past the end of flame wall's 2 second duration, and it will eventually kill the enemy, which shouldn't happen since it should only take flameWallDamage/4 (5 damage) a total of 4 times (20 damage), and the enemy has 30 health.
I'm new to programming, and I've learned most of what I know by trial and error, but I can't seem to figure this out. Throwing a bunch of "this" tags onto it was my latest effort to get things to work right, but I still cannot figure this out.
Could someone please help me out here?
Try making most of the vars public, so you can see them move. Or else toss in a big Debug.Log("duration="+ ... );
and you'll be able to search through the numbers later.
I'm also not sure about Destroy(...,8);
That should kill you after 8 seconds, no matter what.
Answer by syclamoth · Dec 12, 2011 at 01:23 AM
What you are doing here is a pretty inefficient way of doing things. Thankfully, coroutines are here to save you! Try putting that functionality into a coroutine which gets set off when the monster goes into the fire.
// We use this to make sure the monster doesn't get set on fire twice!
private bool onFire;
// Drag and drop the particle emitter in the inspector. It's much faster.
public ParticleEmitter fireEffect;
IEnumerator DoFireDamage(float damageDuration, int damageCount, float damageAmount)
{
onFire = true;
fireEffect.emit = true;
int currentCount = 0;
while(currentCount < damageCount)
{
monsterTwoHealth -= damageAmount;
yield return new WaitForSeconds(damageDuration);
currentCount++;
}
fireEffect.emit = false;
onFire = false;
}
void Update()
{
if(monsterTwoHealth <= 0)
{
Destroy(gameObject);
}
}
void OnTriggerEnter(Collider other)
{
if(other.gameObject.tag == "FlameWall" && !onFire)
{
StartCoroutine(DoFireDamage(flameWallTimer, 4, flameWallDamage);
}
}
A few other things- you say that you have inherited a lot of 'stats' variables from a parent class. It's object-oriented best practice to avoid doing this when you can- it's better to have a 'stats' class which you attach to ever other class that needs them- this way you don't have to assume (or keep track of) any inherited behaviours from the parent class. So-
[System.Serializable]
public class Stats{
public float HP;
public float damage;
public float flameWallDuration;
public float flameWallDamage;
// and so on...
}
Then, in every class that uses it-
// This will show up in the inspector under a little drop-down arrow
public Stats myStats;
Every time you want one of your monster's stats-
myStats.HP;
myStats.flameWallDamage;
This works perfectly, mathwise! Thanks a ton for showing me an alternative to my ridiculously clunky timers. There is one problem, though. The particle effects aren't emitting. I've unparented the fireEffect particle system from the monster, updated the monster's prefab and dragged the particle system into the spot for it in the editor, and I've even tried reparenting the particle system back onto the moster as well, and the particle system just doesn't want to emit. $$anonymous$$gestions?
Well, I can't really explain that. The fireEffect should definitely still be a transform child of the monster, though. They should be part of the same prefab.
Just wanted to update you on the situation. Apparently, I'm just dumb. I didn't reset the position of the particle system to 0, 0, 0 when I attached them to the game object. It was working perfectly the whole time, the particle system was just way off the visible screen. Thanks again!
@syclamoth Hey there! I know it's been many years, but if you're out there and willing to help, I'd be ultra grateful!
I'm new to Unity and C# and my question is: when you do "public Stats mystats;" and then alter the "myStats.HP" variable, doesn't it change the "HP" variable on the "Stats" class itself? $$anonymous$$eaning that if many GameObjects use it, all of them will take damage at once?
Answer by Neuroticaine · Dec 12, 2011 at 02:51 AM
Thanks for the response. I'll give it a shot. I know a lot of it's extremely inefficient, but this is a continuation of a project I did at the start of the semester and I simply didn't have the time to start the scripting from scratch to make it more efficient. In retrospect, I would have made a completely separate class like you suggested. In fact, I've been working on this so much lately that when I'm in bed, trying to fall asleep, I start mentally mapping out how to make it more efficient the next time around. =P
Your answer
Follow this Question
Related Questions
Health bar help 1 Answer
Survival Shooter cant hit the zooooooom bunny 0 Answers
How do I make the object apply damage on trigger? 0 Answers
Damage two objects based on their relativ speed to each other 2 Answers
The damage to my player keeps stacking even after I quit the game and restart. 0 Answers