It seems that a reference got lost when an EventList is invoked

**OS : ** Windows 11
**Needle Engine: ** 3.51.0
**Unity: ** 2022.3.15

Hi everyone, I’m doing some calls to EventList and when I Invoke the EventList, the method which is listening in fact is executed but, a reference to a script inside that method is undefined and therefore the expected behavior is not executed. But is strange because that reference multiplayerController in the start method is not undefined but, when is called in the method paralize, that reference is undefined.

The next is my code :

import { Behaviour, GameObject, serializable } from "@needle-tools/engine";
import { MultiplayerController } from "./PlayerController";
import { LogicGameEvents } from "./TurretBehavior";

export class LogicEventPlayerHandler extends Behaviour{

    @serializable(MultiplayerController)
    multiplayerController !: MultiplayerController; 

    start(): void {
        
        //This line returns that In fact there is a MultiplayerController which is not undefined 
        console.log(this.multiplayerController);
        
        this.setBeginListener(); 
    }

    onDisable(): void {
        this.setStopListeners(); 
    }

    setBeginListener(){
        GameObject.findObjectOfType(LogicGameEvents)!.logicalEvent.addEventListener(this.paralize); 
    }

    setStopListeners(){
        GameObject.findObjectOfType(LogicGameEvents)!.logicalEvent.removeEventListener(this.paralize); 
    }

    paralize(){
        //When the paralize method is invoked for another class, for some reason the  multiplayerController is undefined 
        console.log(this.multiplayerController);
        this.multiplayerController?.paralize(); 
    }
   
}

That event is declare in the class LogicalGameEvents

export class LogicGameEvents extends Behaviour{

    //player_controls_event = new Event("player_controls"); 
    @serializable(EventList)
    logicalEvent !: EventList; 

    public invokeEvents(){
        this.logicalEvent.invoke(); 
    }

}```

And is invoked in `BulletBehavior`  : 

```ts
export class BulletBehavior extends Behaviour{


    private logicalGameEvent !: LogicGameEvents; 

    start(): void {

        this.logicalGameEvent = GameObject.findObjectOfType(LogicGameEvents)!; 

        const direction = this.gameObject.parent!.worldForward;
        const gObj_rb = this.gameObject.getComponent(Rigidbody); 
        gObj_rb!.resetForcesAndTorques(); 
        gObj_rb!.resetVelocities(); 
        gObj_rb!.applyImpulse(direction.normalize().multiplyScalar(1.1));

        this.timedDestroy(); 
    }


    onCollisionEnter(col: Collision) {
        
        //const playerControls = col.gameObject.getComponent(MultiplayerController);  

        // if(playerControls){
        //     //this.dispatchEvent(LogicGameEvents.instance.player_controls_event); 
        //     playerControls.paralize(); 
        // }
        this.logicalGameEvent.invokeEvents(); //< -- esto se esta invocando pegue o no pegue 
        GameObject.destroySynced(this.gameObject); 
        
    }

    private lifeTime : number = 2; 

    timedDestroy = () => {
        if(this.lifeTime === 0){
            GameObject.destroySynced(this.gameObject);  
        }else{
            this.lifeTime--; 
            setTimeout(this.timedDestroy, 1000);
        }
    }

}```

Why does the MultiplayerController reference is not null in the start of  `LogicEventPlayerHandler`  but, when the event `logicalEvent` is called in the method `paralize` of the same class, it comes out that the MultiplayerController  reference (called multiplayerController ) is undefined ?

Hello diegoeloko,

The issue you’re experiencing with the multiplayerController being undefined in the paralize method is likely related to the context (this) in which the method is invoked. When you add this.paralize as an event listener, the invocation context may change, leading to this not referring to the LogicEventPlayerHandler instance anymore.

To fix this, you can use an arrow function to preserve the context when paralize is called. Here’s how you can modify your setBeginListener method:

setBeginListener(){
    const eventListener = () => this.paralize();
    GameObject.findObjectOfType(LogicGameEvents)!.logicalEvent.addEventListener(eventListener); 
}

And also modify the setStopListeners method to remove the listener correctly. You might need to maintain a reference to the event listener if you want to remove it later.

Here’s how your full class would look with the changes:

import { Behaviour, GameObject, serializable } from "@needle-tools/engine";
import { MultiplayerController } from "./PlayerController";
import { LogicGameEvents } from "./TurretBehavior";

export class LogicEventPlayerHandler extends Behaviour{

    @serializable(MultiplayerController)
    multiplayerController !: MultiplayerController; 

    private eventListener: () => void;

    start(): void {
        console.log(this.multiplayerController);        
        this.setBeginListener(); 
    }

    onDisable(): void {
        this.setStopListeners(); 
    }

    setBeginListener(){
        this.eventListener = () => this.paralize();
        GameObject.findObjectOfType(LogicGameEvents)!.logicalEvent.addEventListener(this.eventListener); 
    }

    setStopListeners(){
        GameObject.findObjectOfType(LogicGameEvents)!.logicalEvent.removeEventListener(this.eventListener); 
    }

    paralize(){
        console.log(this.multiplayerController);
        this.multiplayerController?.paralize(); 
    }
}

This should keep this within the paralize method referring correctly to the LogicEventPlayerHandler instance, thus retaining access to multiplayerController.

Let me know if you need any more help or details!

1 replies left - Get a PRO license for more AI replies.
thread_kqtlZoGE2xjlA1dJlZ5MDVaA
Reply to this message to continue the conversation

1 Like

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