Search code examples
c#unity-game-enginelambdagame-developmentobserver-pattern

Why Observer Pattern Doesn't Work Properly In a Unity3d Project?


In my game I have a script attached to a child object(muzzle) of a game object (Pistol -parent object-) that becames SetActive(false) and SetActive(true) frequently.

public class Pistol : BaseBulletSpawner
{
    public override void Start()
    {
        speedTime = 0.5f;
        maxBulletCount = 15;
        currentBulletCount = maxBulletCount;
    }

    private void OnEnable()
    {
        EventManager.OnSpeedIncrease.AddListener(PistolSpeedIncrease);
        Debug.Log("enable");
    }

    private void OnDisable()
    {
        EventManager.OnSpeedIncrease.RemoveListener(PistolSpeedIncrease);
        Debug.Log("disable");
    }

    private void PistolSpeedIncrease()
    {
        speedTime -= 0.05f;
        Debug.Log("increased");
    }
}

I trigger the 'OnSpeedIncreased' unity event only when the parent object is deactivated. In this version of code It prints "enable" and "disable" when it becames active and inactive, but never prints "increased" or changes the speedTime's value no matter how many times I triggered the unity event. I'm sure that the unity event is triggered because I tested this in another script -attached to a game object that never enabled false- and it works.

There is one more confusing. If I recreate like this:

private void OnEnable()
{
    EventManager.OnSpeedIncrease.AddListener(() => Debug.Log("increased"));
    Debug.Log("enable");
}

private void OnDisable()
{
    EventManager.OnSpeedIncrease.RemoveListener(() => Debug.Log("increased"));
    Debug.Log("disable");
}

instead of not working at all, If the object is deactivated for the first time, it prints "increased" once every time I trigger the event, as it should. But if it is active and inactive again, this time it prints two or as many times as this cycle has occurred, every time the event is triggered.

I don't understand why it doesn't work when written in a method in the first place, and don't understand either why does it kinda work(!) when it is written as a lambda expression.

Here is a pic of where the script belongs to. Muzzle Object


Solution

  • From what I am seeing in the code, your code works as expected. At least according to your

    "I trigger the 'OnSpeedIncreased' unity event only when the parent object is deactivated."

    You are unsubscribing from your event, so your handler PistolSpeedIncrease is not called.

    In the second case, lambda is not the same every time. That's why unsubscribe not working and you add a new lambda handler on every OnEnable() call.