Hi, i have a script for the flame of my flamethrower and i’ve debugged all i could i’m using unity remote to test, idk if could cause this, i have a turret that fires like a flamethrower and damage target’s every 0.4 seconds using ontriggerstay2d and 4 enemies in front of it, sometimes hits do not land on 1, 2 or 3 of them i’ve tried to check if any boxes were off at the time, or if anything was disabled and nothing so here’s my code.
void FixedUpdate() {
if (dot_timer > 0)
dot_timer -= Time.deltaTime;
else
{
dot_timer = base_dot_timer;
Debug.Log("should hit");
Debug.Break();
}
}
private void OnTriggerStay2D(Collider2D other)
{
if (dot_timer <= 0)
{
if (other.gameObject.layer == target_layer)
{
Enemy_Manager enemy = other.gameObject.GetComponent<Enemy_Manager>();
enemy.Hp -= damage;
Debug.Log("hit");
enemy.Blink_fx.SetActive(true);
Vector3 screenPoint = Camera.main.WorldToViewportPoint(other.gameObject.transform.position);
bool onScreen = screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
if (onScreen)
{
for (sbyte i = 0; i < 30; i++)
{
if (!game_manager.TextInstPool*.activeInHierarchy)*
{
game_manager.TextInstPool*.transform.position = other.gameObject.transform.localPosition;
game_manager.TextInstPool.SetActive(true);
game_manager.TextPool.text = damage.ToString();
break;
_}
}*_
}
}
}
}
I think the problem is that OnTriggerStay
will not necessarily line up with the FixedUpdate
function. The moment that dot_timer
is 0, there might not be an OnTriggerStay
called. What you should do is make the dot_timer
dependent on OnTriggerStay
. For example,
void FixedUpdate() {
}
private void OnTriggerStay2D(Collider2D other)
{
dot_timer -=.01; //Physics is based on real time, not deltaTime.
if (dot_timer <= 0)
{
dot_timer=base_dot_timer;
//...
@pako @Nomenokes hi here is a piece of my fire turret’s code, sorry that it’s a little big, i use a raycast to check if there is any enemy within the turret’s range so it’ll start the fire, is using a RaycastAll
really cheaper then ontriggerstay
? because i’ve seen a lot of posts saying that raycasts are very expensive since you have to use it every frame, also one thing that bothers me is that when i try to make timed events they seem unaccurate, what is the best way to guarantee that i’ll get the desired effect always at the desired time? i try to use FixedUpdate
for that.
private void FixedUpdate()
{
if (script.Activated)
{
Turret_Enemy_Raycast();
StartAtk();
}
else
CancelAtk();
EndAtk();
}
private void Turret_Enemy_Raycast()
{
hit = Physics2D.Raycast(origin, new Vector2(script.Dir.x, 0), script.Range, layer_mask_hit);
hit2 = Physics2D.Raycast(origin2, new Vector2(-script.Dir.x, 0), script.Range, layer_mask_hit);
Debug.DrawRay(origin, new Vector2(script.Dir.x, 0));
Debug.DrawRay(origin2, new Vector2(-script.Dir.x, 0));
if (hit)
{
Turret_Fire();
}
else
{
if (isAtk)
{
for (sbyte i = 0; i < 2; i++)
{
if (fire*.Firing)*
{
fire*.Firing = false;*
fire*.Em = false;*
fire*.Fading = true;*
isAtk = false;
fadingNum = i;
break;
}
}
}
}
if (hit2)
{
Turret_Fire2();
}
else
{
if (isAtk2)
{
for (sbyte i = 0; i < 2; i++)
{
if (fire2*.Firing)*
{
fire2*.Firing = false;*
fire2*.Em = false;*
fire2*.Fading = true;*
isAtk2 = false;
fadingNum2 = i;
break;
}
}
}
}
}
I’ve come up with and answer, it happens that ontriggerstay isn’t reliable for any over time effect, and also RaycastAll
is very much more expensive than the situation demmands, to solve this i’ve created a enemy list, whenever an enemy collides with the fire(OnTriggerEnter2D
), it will add him into the list, (OnTriggerExit2D
) will remove him from the list, and when the timer reaches 0 it’ll apply damage to every enemy on the list, i believe this is one of the best ways to make AoE and DoT heres my fire’s code now:
private Game_Manager game_manager;
private List<Enemy_Manager> enemies;
private int target_layer;
private float base_dot_timer;
private float dot_timer = 0;
private int damage;
private Vector2 dir;
// Use this for initialization
void Start () {
Vector3 scale = transform.localScale;
scale.Set(-dir.x, 1, 1);
transform.localScale = scale;
enemies = new List<Enemy_Manager>();
}
// Update is called once per frame
void FixedUpdate() {
if (dot_timer > 0)
dot_timer -= Time.deltaTime;
else
{
for(sbyte i = 0; i < enemies.Count; i++)
{
enemies*.Hp -= damage;*
Debug.Log(“hit”);
enemies*.Blink_fx.SetActive(true);
_Vector3 screenPoint = Camera.main.WorldToViewportPoint(enemies.transform.position);
bool onScreen = screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
if (onScreen)
{
for (sbyte s = 0; s < 30; s++)
{
if (!game_manager.TextInstPool~~.activeInHierarchy)~~
{_
game_manager.TextInstPool~~.transform.position = enemies.transform.localPosition;
*game_manager.TextInstPool.SetActive(true);~~
game_manager.TextPool~~.text = damage.ToString();~~
break;
}
}
}
}
dot_timer = base_dot_timer;
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.layer == target_layer)
{
enemies.Add(other.gameObject.GetComponent<Enemy_Manager>());
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.gameObject.layer == target_layer)
{
enemies.Remove(other.gameObject.GetComponent<Enemy_Manager>());
}
}
thank for all your answers and sorry being unclear with my problem