FPS Movement Issues

Hello there, I’m having an issue with my FPS movement. When I turn in a direction and attempt to move forward in that direction I end up moving forward in the player entity’s initial direction; the camera isn’t tracking rotations in what it considers forward, back, left and right. I’m going off this tutorial for my implementation of movement: http://developer.playcanvas.com/ja/tutorials/legacy/advanced/fps-controller/

I’m using this because I want gravity and the other tutorial doesn’t offer this since it uses forces to apply movement. Here is my code:

//pc.script.attribute("camera", "entity", null); // optional, assign a camera entity, otherwise one is created
pc.script.attribute("power", "number", 1000);
pc.script.attribute("lookSpeed", "number", 0.1);


pc.script.create('player', function (app) {
    var force = new pc.Vec3();
    var shoot=true;
   var origin = new pc.Vec3();
    var Jump=400;
    var rayEnd = new pc.Vec3();
    var groundCheckRay = new pc.Vec3(0, -1.76, 0);
    
    var player = function (entity) {
        this.entity = entity;
        this.camera=null;
        //this.eulers = entity.getEulerAngles(); 
        this.jumpImpulse = new pc.Vec3(0, Jump,0);
        this.hit=false;
        //this.tmp=new pc.Vec3();
        this.ballVar=false;
        this.ballName="";
        this.speed=15;
        this.onGround = true;
        
        this.x = new pc.Vec3();
        this.z = new pc.Vec3();
        this.heading = new pc.Vec3();
    };

   player.prototype = {
        // Called once after all resources are loaded and before the first update
        initialize: function () {
            // Listen for mouse 
            // events
             //this.entity.rigidbody.setAngularFactor(0);
            this.camera = app.root.findByName('Camera');
            app.root.findByName("Dodgeball UI").enabled=false;
            app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
           // app.mouse.on("mousemove", this._onMouseMove, this);

            // when the mouse is clicked hide the cursor
          //  app.mouse.on("mousedown", function () {
            //    app.mouse.enablePointerLock();
           // }, this);  
            

            // Check for required components
            //if (!this.entity.collision) {
           //     console.error("First Person Movement script needs to have a 'collision' component");
          //  }

           // if (!this.entity.rigidbody || this.entity.rigidbody.type !== pc.BODYTYPE_DYNAMIC) {
               // console.error("First Person Movement script needs to have a DYNAMIC 'rigidbody' component");
          //  }
            
            this.ball = app.root.findByName('Static Ball'); //make clone
            //var uiEntity = app.root.findByName('UI');
            
            //if (!this.camera) {
           //     this._createCamera();
          //  }
            
           // this.entity.rigidbody.setAngularFactor(0);
           // this._vel = new pc.Vec3(0, 0, 0);
          //  this._angSpeed = 0;
            
            
            
        },
         onKeyDown: function (event) {
            event.event.preventDefault();
        },
       
       

        // Called every frame, dt is time in seconds since last update
        update: function (dt) {
           // onGround= this._checkGround();
            
            var input=false;
          //  console.log(position.x);
            // Get camera directions to determine movement directions
        //  var transform = this.camera.getWorldTransform();
         var transform = this.camera.getWorldTransform();

            transform.getZ(this.z);
            this.z.y = 0;
            this.z.normalize();            
            
            transform.getX(this.x);            
            this.x.y = 0;
            this.x.normalize();            
            
            this.heading.set(0, 0, 0);

            // Strafe left/right
        //    if ((app.keyboard.isPressed(pc.KEY_A)|| app.keyboard.isPressed(pc.KEY_D)||app.keyboard.isPressed(pc.KEY_W)||app.keyboard.isPressed(pc.KEY_S)))
           // {
                 //input=true; 
            if (app.keyboard.isPressed(pc.KEY_A)) {
                this.heading.sub(this.x); //changed this.x to forward 
                input=true;
                }     
             if (app.keyboard.isPressed(pc.KEY_D)) {
                this.heading.add(this.x); 
                  input=true;
                 }
            
            // Move forwards/backwards
            if (app.keyboard.isPressed(pc.KEY_W)) {
                this.heading.sub(this.z);  
                 input=true;
            } 
             if (app.keyboard.isPressed(pc.KEY_S)) {
                this.heading.add(this.z);
                  input=true;
             }
           if (input===true)
               this.heading.normalize();
         //   }
                if (this.onGround===true)
                {
                   // var direction=this.heading;
                    this.entity.rigidbody.activate();
                    this.heading.scale(this.speed);   
                    this.entity.rigidbody.linearVelocity = this.heading;
                }
  
            if (app.keyboard.isPressed(pc.KEY_SPACE)){
                this.jump();
           }

            // use direction from keypresses to apply a force to the character
           // if (x !== 0 && z !== 0) {
            //   force.set(x, 0, z).normalize().scale(this.power);
             //  this.entity.rigidbody.applyForce(force);
           // }
            
            // update camera angle from mouse events
         //  this.eulers.y = pc.math.clamp(this.eulers.y, -90, 90);
           // this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0);
            
        },

       // _onMouseMove: function (e) {
            // If pointer is disabled
            // If the left mouse button is down update the camera from mouse movement
           // if (pc.Mouse.isPointerLocked() || e.buttons[0]) {
               // this.eulers.x -= this.lookSpeed * e.dx;
               // this.eulers.y -= this.lookSpeed * e.dy;
                //this.eulers.y = pc.math.clamp(this.eulers.y, -90, 90);
           // }
    //    },
        
        onMouseDown: function(event){
            event.event.preventDefault();
             
            if(event.button === pc.MOUSEBUTTON_LEFT){
               // console.log(this.ballVar);
              if (this.ballVar===true/*&&this.hit===false*/)
              {
                  //console.log("Fire");
                  this.ballVar=false;
                  app.root.findByName("Dodgeball UI").enabled=false;
                  var wp = this.entity.getPosition();
                  this.ball=app.root.findByName(this.ballName);
                  if(this.ball){
                       this.ball.rigidbody.linearVelocity =pc.Vec3.ZERO;
                       this.ball.rigidbody.angularVelocity=pc.Vec3.ZERO;
                  }
              
                  var f = this.camera.forward.clone();  
                  var u = this.camera.up.clone();
                  wp.x = wp.x+f.x;
                  wp.y = wp.y+f.y+0.5;
                  wp.z = wp.z+f.z;
                  this.ball.rigidbody.teleport(wp);
                 // console.log("World Position "+wp.x +" "+wp.y+" "+wp.z);
                  this.ball.rigidbody.linearVelocity =pc.Vec3.ZERO;
                  this.ball.rigidbody.angularVelocity=pc.Vec3.ZERO;              
                 // this.ball.translateLocal(f.scale(4));
                  this.ball.rigidbody.linearVelocity =this.entity.rigidbody.linearVelocity;
                  this.ball.rigidbody.angularVelocity=this.entity.rigidbody.angularVelocity;
                  //console.log("Camera Forward: "+f.x +", "+ f.y +", "+f.z);            
                  var ballpulse = new pc.Vec3();                            
                 // console.log("impulse "+ballpulse);
                  ballpulse.add(f.scale(30));              
                //  console.log("impulse "+ballpulse);
                   this.ball.rigidbody.applyImpulse(ballpulse);
                   this.ball.script.BallCollider.active=true;
                }
            }
        },
        
       
       _createBall: function(){},
       
     //   _createCamera: function () {
            // If user hasn't assigned a camera, create a new one
         //   this.camera = new pc.Entity();
          //  this.camera.setName("First Person Camera");
           // this.camera.addComponent("camera");
           // this.entity.addChild(this.camera);
          //  this.camera.translateLocal(0.16, 0.5, 0);
            //var crosshairUI =app.root.findByName('crosshair');
            //crosshairUI.teleport(this.camera.getPosition());
       // },
        
        reset:function(){
             newBall.rigidbody.teleport(0.044,3.095,1.921);
             newBall.rigidbody.linearVelocity = pc.Vec3.ZERO;
             newBall.rigidbody.angularVelocity = pc.Vec3.ZERO;
        },
       
      jump: function () {
          //console.log(this.entity.getPosition().y);
            if (onGround===true) {
                //console.log("jumping"); 
                this.entity.rigidbody.activate(); 
                this.entity.rigidbody.applyImpulse(this.jumpImpulse, origin);
                onGround = false;                
            }
        }, 
        
            _checkGround: function () {
            var pos = this.entity.getPosition();
            rayEnd.add2(pos, groundCheckRay);
            onGround = false;

            // Fire a ray straight down to just below the bottom of the rigid body, 
            // if it hits something then the character is standing on something.
            app.systems.rigidbody.raycastFirst(pos, rayEnd, function (result) {
                onGround = true;
            }.bind(this));

        }
   
            };
         return player;                                   
   });

Any help would be appreciated, thank you in advance.

Can you share a link to your project? Also you are using the legacy script system which might be on purpose, but if not just letting you know that the new scripting system is a lot more powerful and also is accompanied by the new code editor.

https://playcanvas.com/project/380063/overview/you-got-balls

We are intentionally using the legacy because it uses applications of velocities to control movement, not forces.

You can use the new scripting system and port the legacy FPS script over/modify the current FPS script to suit your needs. Using velocities to control movement isn’t unique to the legacy scripting system.

As for your actual problem, the player.js script has this line to find the camera entity:

this.camera = app.root.findByName('Camera');

However, in your project, you have two cameras, one in the Invisible Room group:

And another under the player entity:

Currently, the script is finding the first one hence the heading for going forwards, backwards, etc doesn’t change.

To fix this, I would:

  1. Use a script attribute and reference the correct camera entity directly
  2. Change the name of the cameras and update the script
  3. Change that line to only search the children: this.camera = this.entity.findByName('Camera');