Make the VFX work for the enemy when dying from a collision with a player

When a player’s ship crashes into an enemy, the enemy is destroyed, but without an explosion.

If a collision with an enemy takes 200hp from the player, while the player has 500hp in total, then:

  • First encounter: the enemy is destroyed without video effect, the player is alive (300hp)

  • Second encounter: the enemy is destroyed again without video effect, the player is alive again (100hp)

  • Third collision: enemy dies without video effect, the player dies with video effect (I connected the effect to the player)

How to make the video effect work for the enemy when dying from a collision with a player?

Perhaps I will solve this on my own, but I will be glad to receive your suggestions. If I decide on my own, I will have to turn over all the scripts and prefabs, but what if someone has already done what I am writing about gracefully and intelligently?

Hi Artyom,

What do you mean by second and third encounter/collision? If the enemy gets destroyed in the first encounter, there cannot be any additional encounters in the future.

Hi Nina,

By second and third encounter/collision I mean the encounter from the Player’s Ship point of view. By the way, it makes no difference: our enemies have no VFX on their death from the collision with the player.
However, when the player dies after the third collision, the particle effect (its deathVFX) is activated.
GIF - collisions

This is my question: how to make sure that when the enemy collides with the player, the video effect of the enemy’s explosion is triggered?

Where does the animation get triggered? And what is the animation? A particle system that gets instantiated? Or a particle system that is assigned to the enemy?

If your enemy explodes when a laser hits it, check the code and try to figure out what prevents the enemy from exploding when it collides with the player. For Unity, there is no such thing as “enemy”, “player” or “laser”. They are all colliders and/or game objects for it. If you don’t distinguish between the objects via code, they all should trigger the enemy’s explosion.

The animation is triggered in Enemy.cs here:

    private void OnTriggerEnter2D(Collider2D other)
    {
        Debug.Log("Collision");
        DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
        if (!damageDealer || tag != "Player") { return; }
        ProcessHit(damageDealer); // this triggers the animation
    }

I added condition, so now it can be read as:
IF we have no Damage Dealer component OR tag is not equal to “Player” THAN return

Also, I have added a Debug.Log to the ProcessHit method:

    private void ProcessHit(DamageDealer damageDealer)
    {
        Debug.Log("Process Hit is ON");
        health -= damageDealer.GetDamage();
        damageDealer.Hit();
        if (health <= 0)
        {
            Die();
        }
    }

When the player collides with the enemy, Unity console says:
image

So, the problem is: Process Hit method is not activated by Enemy AND Player collision.

Your recommendation is:

Of course, I did it. Laser have DamageDealer component. Player - doesn’t. Ok, I tried to add to the Player DamageDealer component. It doesn’t work. Enemy death VFX still not active after death from the collision with the player.

Also, Laser has Rigidbody2D component. But adding to Player prefab Rigidbody2D component does not solve the problem, but only aggravates it.

After I realised what the condition if (!damageDealer || tag != "Player") { return; } also breaked the Enemy-PlayerLaser collision - I have deleted it.

With usual if (!damageDealer) { return; } and DamageDealer (Damage on Player’s DD component = 100) component on the player, enemy and player collision kills the player with the 1st encounter!

I’m confused. That is why I am asked about a neat solution.

P.S. I also tried this (with Damage Dealer added to Player):

    private void OnTriggerEnter2D(Collider2D other)
    {
        Debug.Log("Collision");
        DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
        if (other.tag == "Player")
        {
            ProcessHit(damageDealer);
        }
        if (!damageDealer) { return; }
        ProcessHit(damageDealer);
    }

It worked only at the half. ProcessHit method was activated, but both player and enemy were destroyed without any deathVFX. So, I removed DD component from the player, deleted if (other.tag == "Player") condition.

I’m afraid I cannot see any animation anywhere. Maybe I wasn’t clear. By animation, I’m referring to the Unity animations. In your code, you would control an Animator object.

I assume you instantiate a VFX prefab in the Die method, don’t you?

When the Player collides with the enemy, three messages saying “Collision” get logged into your console?

I think this condition is not correct:

if (!damageDealer || tag != "Player") { return; }

Since this line is in the Enemy class, tag refers to the instance of type Enemy. The enemy is not supposed to have the “Player” tag, thus this condition is very likely always true.


At the moment, I’m slightly confused about which problem we are talking here. There was something about three encounters and a collision, and something about the enemy which does not “explode”.

If you seek a neat solution, I’d suggest to rewrite a part of the solution while simultaneously reenacting the logic you want to implement.

Assuming you want to wire up some logic in the Enemy class when the enemy gets hit by “something”, you would use the OnTriggerEnter2D method. Ideally, you would start with logging meaningful messages into your console.

private void OnTriggerEnter2D(Collider2D other)
{
    Debug.Log(Time.frameCount + " --- Enemy: OnTriggerEnter2D was called.");
    Debug.Log(Time.frameCount + " --- Enemy collided with " + other.name);
}

Then you could check bit by bit what information you get in your console and what you can access. After you figured out what data you can receive, you “phrase” your expectations.

private void OnTriggerEnter2D(Collider2D other)
{
    Debug.Log(Time.frameCount + " --- Enemy: OnTriggerEnter2D was called.");
    Debug.Log(Time.frameCount + " --- Enemy collided with " + other.name);

    DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
    if (!damageDealer)
    {
        Debug.Log(Time.frameCount + " --- " + other.name + "has no DamageDealer attached.");
        return;
    }
   
    ProcessHit(damageDealer);
}

Is the ProcessHit method always supposed to get called when the other game object has got a DamageDealer attached? If so and if the trigger method works as expected, leave it alone and focus on the ProcessHit method. If you need information on the colliding game object, define the ProcessHit method with a second parameter.

Make every method work and start at the beginning of the “chain”. The “chain” starts in the OnTriggerEnter2D method which calls ProcessHit which calls multiple methods which could prevent the VFX prefab from getting instantiated.

And if you approach this problem systematically, you will also be able to realise your idea with the three encounters.

Since I am introducing a number of additional features into the game, it is more profitable for me to reduce the cost of solving the problem described in the topic.
What happened? Problem: enemies disappear from collisions with the player without playing the video effect of death (while the Damage Dealer script is not attached to the player). If a Damage Dealer script is attached to the player - after a collision with an enemy, both the enemy and the player disappear.

What I’ve done? Solution: I wanted to have a response when hitting enemies - it doesn’t matter if the player’s laser hit the enemy or the player collided with the enemy. For this, I did:

    [Header("Hit VFX and SFX")]
    [SerializeField] GameObject hitVFX;
    [SerializeField] float durationOfHit = 1;
    [SerializeField] AudioClip hitSound;
    [SerializeField] [Range(0, 1)] float hitSoundVolume = 0.4f;

And:

    private void OnTriggerEnter2D(Collider2D other)
    {
        GameObject explosionHit = Instantiate(hitVFX, transform.position, transform.rotation);
        Destroy(explosionHit, durationOfHit);
        AudioSource.PlayClipAtPoint(hitSound, Camera.main.transform.position, hitSoundVolume);
//....................................................

Yes, I avoided doing an in-depth study of the problem. it’s often easier to rewrite code from scratch than trying to solve a problem inside it. However, now the player encounters with enemies do not look empty.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms