Search code examples
unity-game-enginecollision-detection

Why the component automatically was removed on collision event of the Unity?


My English skill is poor I'm not a native English speaker. Please understand.

I want to make the logic that detecting collision

For that, I make a character class. The Character class inherits the MonoBehaviour of the Unity system and has a feature as below.

  1. The class has the container to put the skill was collided with own.
  2. The class has the coroutine to show the status of the container. This coroutine starts when the Character class starts.
  3. The class overrides OnTriggerEnter2D function of the Unity system. In this function, the skill that collides with own is added to the container.

I made the above feature as below code.

public class Character : MonoBehaviour
{
    private ConcurrentDictionary<Skill, float> _skills = new ConcurrentDictionary<Skill, float>();


    protected virtual void Start()
    {
        StartCoroutine(Check());
    }

    private IEnumerator Check()
    {
        float delayTime = 0.1f;

    First:
        yield return new WaitForSeconds(delayTime);

        foreach (var skill in _skills.Keys.ToList())
        {
            Debug.Log($"_skills: {skill}");
        }

        goto First;
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag != "cold_wind") return;

        var skill = collision.GetComponent<Skill>();
        _skills.TryAdd(skill, 100);
    }
}

And I added BoxCollider2D component to the prefab that to add the above Character class.

After then I made the Skill class. I omit the Skill class because the Skill class doesn't have a feature yet. I added BoxCollider2D and RigidBody2D components to the prefab that to add the Skill class.

Finally I checked the Simulated function of the RigidBody2D to receive a collision event.

enter image description here

The program executes as the below sequence.

  1. The skill is generated for 3 seconds and it collides with the character.
  2. OnTriggerEnter2D function of the Character was called and skill that collided was added to the container. (Concurrent<Skill, float>)
  3. The Check coroutine shows the skill be included in the container.

Here, I have the problem. Logically I think the Skill class included in the container must not be removed automatically.

But after 3 seconds (the skill effect appears for 3 seconds) if the skill effect disappears then the Skill class included in the container was removed. At the result Check coroutine shows null as below.

enter image description here

Could someone tell me what I did wrong?

Any advice would be much appreciated.

Thanks for reading.


Solution

  • Most likely everything you are doing is working as intended. The one mistake would be unexpected behavior with TryAdd, where the value added can be null.

    Inside of your OnTriggerEnter2D function, add a check to determine what you collided with to only check for spells. The easiest way to do this is check the tag of the object. For all of your spells, add a tag that you can check against, then change your collision code to look something like

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "SpellTagHere")
        {
            // the issue is this line can result in NULL if another object collides with your player
            var skill = collision.GetComponent<Skill>();
            
            // meaning a null is added here
            _skills.TryAdd(skill, 100);
        }
    }