Arcade physics sometimes miss collide

Hi there,
Im facing with an issue.
My use case is: When the scene have a lots of objects make fps drop down to ~20, the character sprite may not collide with map layer. Even when fps at 60, in rarely case, character sprite still miss collide with map layer.
My code similar to below. Am i missing something?

this.map = this.make.tilemap({ key: TEXTURE.CHAR_SEL_TILED_MAP });

this.tileset = this.map.addTilesetImage(
  TEXTURE.TILE_TRANSPARENT,
  TEXTURE.TILE_TRANSPARENT
) as Phaser.Tilemaps.Tileset;

this.layer = this.map.createLayer(
  TEXTURE.PLATFORM,
  this.tileset,
  0,
  0
) as Phaser.Tilemaps.TilemapLayer;

this.layer.setCollisionByProperty({ collides: true });

this.physics.world.addCollider(
  this.playerGroup,
  this.layer,
  (player: any, tile: any) => {}
);

:wave:

What’s in scene update()? What size are the tiles?

because of i was use addCollider so that in update() i do nothing else key capture to control character movement.
The tiles size is 32x32 pixels

You can try increasing tileBias (default is 16) in the Arcade Physics config.

What’s the code in update()?

1 Like

Yep, let me try to increase tileBias
below is my update() code

    update(time: number, delta: number): void {
        this.characterControl(this.player);
    }

    protected characterControl(character: CharacterContainer): void {
        if (this.input.keyboard && character) {
            if (!character.controlled) {
                this.getKeyByFunction(FUNCTION_KEYS.MOVE_LEFT).on(Phaser.Input.Keyboard.Events.UP, () => {
                    this.controlServerSync(character, FUNCTION_KEYS.MOVE_LEFT, false, this.connectedRoom);
                    character.mLeft(true);
                });
                this.getKeyByFunction(FUNCTION_KEYS.MOVE_RIGHT).on(Phaser.Input.Keyboard.Events.UP, () => {
                    this.controlServerSync(character, FUNCTION_KEYS.MOVE_RIGHT, false, this.connectedRoom);
                    // Move character right
                    character.mRight(true);
                });
                this.getKeyByFunction(FUNCTION_KEYS.FALL_JUMP).on(Phaser.Input.Keyboard.Events.UP, () => {
                    this.controlServerSync(character, FUNCTION_KEYS.FALL_JUMP, false, this.connectedRoom);
                    character.mDown(true);
                });
            }
            character.controlled = true;
            if (this.getKeyByFunction((FUNCTION_KEYS.MOVE_LEFT)).isDown) {
                this.controlServerSync(character, FUNCTION_KEYS.MOVE_LEFT, true, this.connectedRoom);
                // Move character left
                character.mLeft();
            }
            if (this.getKeyByFunction((FUNCTION_KEYS.MOVE_RIGHT)).isDown) {
                this.controlServerSync(character, FUNCTION_KEYS.MOVE_RIGHT, true, this.connectedRoom);
                // Move character right
                character.mRight();
            }
            if (this.getKeyByFunction((FUNCTION_KEYS.JUMP)).isDown) {
                this.controlServerSync(character, FUNCTION_KEYS.JUMP, true, this.connectedRoom);
                character.mJump();
            }
            if (this.getKeyByFunction((FUNCTION_KEYS.FALL_JUMP)).isDown) {
                this.controlServerSync(character, FUNCTION_KEYS.FALL_JUMP, true, this.connectedRoom);
                character.mDown();
            }
        }
    }

    getKeyByFunction(fn: FUNCTION_KEYS): Phaser.Input.Keyboard.Key {
        const keyCode = ClientContext.instance.getKeyFunction(fn);
        const exists = this.input.keyboard?.keys?.filter(key => key && key.keyCode === keyCode);
        if (exists && exists.length > 0) {
            return exists[0];
        }
        return this.input.keyboard?.addKey(keyCode) as Phaser.Input.Keyboard.Key;
    }

And what’s in mDown() etc.?

the mDown(), mLeft(), mRight() … method just control the velocity of character sprite and play corresponds animation… similar to this:

Note: this reference to character class that extends from Phaser.GameObjects.Container

    blockMove(): this {
        this.blockingMove = true;
        this.setVelocityX(0);
        this.setVelocityY(0);
        return this;
    }

    mLeft(release?: boolean): this {
        this.setPressTime(FUNCTION_KEYS.MOVE_LEFT, !release);
        const scene = (this.scene as BaseScene);
        if (this.body && !this.blockingMove) {
            if (release) {
                this.emit(EVENT.CONTROL_RELEASE_X);
                // @ts-ignore
                this.setVelocityX(0);
            } else {
                this.emit(EVENT.CONTROL_LEFT);
                // @ts-ignore
                this.setVelocityX(-this.velocityX);
            }
        }
        return this;
    }

    mRight(release?: boolean): this {
        this.setPressTime(FUNCTION_KEYS.MOVE_RIGHT, !release);
        const scene = (this.scene as BaseScene);
        if (this.body && !this.blockingMove) {
            if (release) {
                this.emit(EVENT.CONTROL_RELEASE_X);
                // @ts-ignore
                this.setVelocityX(0);
            } else {
                this.emit(EVENT.CONTROL_RIGHT);
                // @ts-ignore
                this.setVelocityX(+(process.env.DEFAULT_VELOCITY_X || this.velocityX));
            }
        }
        return this;
    }

    mJump(): this {
        this.setPressTime(this.checkKeyDown(FUNCTION_KEYS.HIGH_JUMP) ? FUNCTION_KEYS.HIGH_JUMP : FUNCTION_KEYS.JUMP, true);
        // @ts-ignore
        if (this.body && this.canJump) {
              this.emit(EVENT.CONTROL_JUMP);
              // @ts-ignore
              this.setVelocityY(-this.velocityY);
        }
        return this;
    }

    mDown(release?: boolean): this {
        this.setPressTime(FUNCTION_KEYS.FALL_JUMP, !release);
        // @ts-ignore
        if (this.body && this.onFloor()) {
            if (release) {
                this.blockingMove = false;
                this.emit(EVENT.CONTROL_RELEASE_D);
            } else {
                this.blockMove();
                this.emit(EVENT.CONTROL_DOWN);
                // @ts-ignore
                this.setVelocityX(0);
            }
        }
        return this;
    }

I don’t have any more ideas. Unless you’ve turned off Arcade Physics fixed-step, the physics separations shouldn’t be affected by the render FPS, although something in your code might be.

1 Like

Hmm… i also have no ideas, but after set tile bias to 32, i have not see the issue again.
If it still happens, i will give a try to turn of fixed step
Thanks for your support

No, don’t turn off fixed-step. :slight_smile:

1 Like