[SOLVED] Application Event and postUpdate() method

Hi!

I run an event in the camera script and listen to it in the script move the player using this.app. The event conveys the camera Euler angles that are used to set the Euler angles of the player entity. However, I get a delay in rotation the player entity. If I access the script directly using pc.ScriptComponent, then everything works correctly. Can I use listening to an event instead of calling the script directly from the code?

Link to the project: https://playcanvas.com/editor/scene/678268
Code from project:

var Mooooooove = pc.createScript('mooooooove');

// initialize code called once per entity
Mooooooove.prototype.initialize = function() {
    
    this.camera = this.app.root.findByName('Camera');
    var self = this;
    
    // does not work
    this.app.on('gun', function(pitchAngleMax, pitchAngleMin, angle) {
        
        // var targetY = angle.y;
        // var targetAngle = new pc.Vec3(0, targetY, 0);
        // self.entity.setEulerAngles(targetAngle);
        
    });
    
    
};

// works
// Mooooooove.prototype.postUpdate = function(dt) {
    
//     var targetY = this.camera.script.playerCameraMovement.eulers.x;
//     var targetAngle = new pc.Vec3(0, targetY, 0);
//     this.entity.setEulerAngles(targetAngle);
    
// };

Looks like a script execution order issue. When does event ‘gun’ get fired?

The ‘gun’ event is fired in the camera control script, in the postUpdate() method, after the current camera angle is calculated.

I’ve ‘fixed’ it but not 100% sure why it fixes the issue. If you fire the event before setting the viewEntity’s rotation in the postUpdate call, it’s fine:

PlayerCameraMovement.prototype.postUpdate = function(dt) {
    deltaTime = dt;
   
    var targetY = this.eulers.x;
    var targetX = this.eulers.y;
    
    var targetAngle = new pc.Vec3(-targetX, targetY, 0);
    
    this.app.fire('gun', this.pitchAngleMax, this.pitchAngleMin, targetAngle);

    if (newAngle % 360 > this.pitchAngleMin && newAngle % 360 < this.pitchAngleMax) {
        this.viewEntity.setEulerAngles(targetAngle);
        this.entity.setPosition(this._getWorldPoint());
        // this.entity.lookAt(this.cameraTargetEntity.getPosition());
    }
    
    if (newAngle % 360 > this.pitchAngleMax) {
        this.eulers.y = this.pitchAngleMax - 90;
    }
    
    if (newAngle % 360 < this.pitchAngleMin) {
        this.eulers.y = this.pitchAngleMin - 90;
    }
};

It’s a bit odd as I’m not sure what could be causing the player entity to be a frame behind in the original code :thinking:

2 Likes

This does look a bit over-complicated.

You’ve got a player movement script, a camera movement script, and then the mooooooove script that orients the overall Player entity. All 3 have postUpdate functions that don’t have a defined execution order.

When I run your scene, the mooooooove script postUpdate function is executed before the playerCameraMovement script. The event is essentially being fired when the postUpdate of the playerCameraMovement script has completed (so afterwards).

I think you should simplify how your player movement is handled, to be honest. It’s really hard to see what’s going on.

This is my test project, and maybe I misled a bit. :sweat_smile:

The playerMovement script is an old script that I want to replace with a script that uses application events. About the order of execution, apparently this is my mistake. Thanks for the help! :slightly_smiling_face:

This problem arose with the player control script. The weapon control script worked correctly. I changed the code according to your example, and the player control also worked correctly.