[SOLVED] Help with camera realtivity

Hey, this forum has been incredibly responsive and helpful! I’m not asking for you to do the work for me just point me in the right direction or give me a nudge at least.

I have this script working currently.

var PlayerCameraMove = pc.createScript('PlayerCameraMove');

PlayerCameraMove.attributes.add('camera', {
    type: 'entity',
    description: 'Optional, assign a camera entity, otherwise one is created'
});

PlayerCameraMove.attributes.add('power', {
    type: 'number',
    default: 2500,
    description: 'Adjusts the speed of player movement'
});

PlayerCameraMove.attributes.add('lookSpeed', {
    type: 'number',
    default: 0.25,
    description: 'Adjusts the sensitivity of looking'
});

PlayerCameraMove.attributes.add('jumpPower', {
    type: 'number',
    default: 200.0
});

PlayerCameraMove.attributes.add('raycastPlayerBase', {
    type: 'entity'
});

// initialize code called once per entity
PlayerCameraMove.prototype.initialize = function() {
    this.force = new pc.Vec3();
    this.eulers = new pc.Vec3();
    
    this.jumping = {
        state: false
    };
    
    var app = this.app;
    
    // Listen for mouse move events
    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");
    }
};

// update code called every frame
PlayerCameraMove.prototype.update = function(dt) {
    // If a camera isn't assigned from the Editor, create one
    if (!this.camera) {
        this._createCamera();
    }
    
    var force = this.force;
    var app = this.app;

    // Get camera directions to determine movement directions
    var forward = this.camera.forward;
    var right = this.camera.right;
       

    // movement
    var x = 0;
    var z = 0;

    // Use W-A-S-D keys to move player
    // Check for key presses
    if (app.keyboard.isPressed(pc.KEY_A)) {
        x -= right.x;
        z -= right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_D)) {
        x += right.x;
        z += right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_W)) {
        x += forward.x;
        z += forward.z;
    }

    if (app.keyboard.isPressed(pc.KEY_S)) {
        x -= forward.x;
        z -= forward.z;
    }

    // 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);
    }
    
    if (app.keyboard.wasPressed(pc.KEY_SPACE)) {
        if (this.jumping.state === false) {
            this.entity.rigidbody.applyImpulse(0, this.jumpPower, 0);
            this.jumping.state = true;
        }
    } else if (this.jumping.state === true) {
        // If the raycast finds a collision, we assume it is an obect we can land on, we therefor reset our jump state so we can jump again.
        if (this._checkBelow() !== null) {
            this.jumping.state = false;
        }
    }

    // update camera angle from mouse events
    this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0);
    
    this.eulers.y = pc.math.clamp(this.eulers.y, -80, 80);
    this.eulers.x = pc.math.clamp(this.eulers.x, -80, 80);
};

PlayerCameraMove.prototype._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;
    }            
};

PlayerCameraMove.prototype._checkBelow = function() {
    return this.app.systems.rigidbody.raycastFirst(this.entity.getPosition(), this.raycastPlayerBase.getPosition());
};

PlayerCameraMove.prototype._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, 0.5, 0);
};

I want to get the player to turn to face the direction of the camera, or turn once the camera hits its bounds of left or right. How can I accomplish this? What am I looking to do? Is it simple enough to somehow feed to the character my camera’s current facing direction?

3 Likes

Hello @Aaron_B,
This is the normal first person movement right? (Edit: With jump)

@Gabriel_Dobrzynski Yes exactly :smiley:
Edit: That and i have clamped the camera to 80 degrees (i think it’s degrees)

1 Like

Edit: I am very sorry I was misunderstood

Im not sure then :confused:

What do you mean by that?

Nevermind, You can use raycasting again to detect if something touches its left or right. And when something is there it sets the eulers to a number for the right.

1 Like

@Gabriel_Dobrzynski No worries! Thanks for trying :slight_smile:

@Fus_ion so ultimately i want to effect the eulers of the model (hitbox) based on the direction of the camera?

oh set the angles of the model the same way you did to the camera:

this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0);
this.hitbox.setLocalEulerAngles(0, this.eulers.x, 0);

@Fus_ion ok so i added that line of code and added this line in the initialize.

var hitbox = this.hitBox;

but i get this error: Cannot read property ‘setLocalEulerAngles’ of undefined

So i’m not defining it properly? I also set an attribute called hitbox and made it an entity and added the hitbox capsule to its attribute slot. I’m new to javascript so i’m trying to understand the proper way to define something.

Have you added the camera to the attribute?

Edit: Nevermind, I see the script does that when you have forget that.

Screenshot 2021-03-10 132827

var PlayerCameraMove = pc.createScript('PlayerCameraMove');

PlayerCameraMove.attributes.add('camera', {
    type: 'entity',
    description: 'Optional, assign a camera entity, otherwise one is created'
});

PlayerCameraMove.attributes.add('power', {
    type: 'number',
    default: 2500,
    description: 'Adjusts the speed of player movement'
});

PlayerCameraMove.attributes.add('lookSpeed', {
    type: 'number',
    default: 0.25,
    description: 'Adjusts the sensitivity of looking'
});

PlayerCameraMove.attributes.add('jumpPower', {
    type: 'number',
    default: 200.0
});

PlayerCameraMove.attributes.add('raycastPlayerBase', {
    type: 'entity'
});

PlayerCameraMove.attributes.add('hitBox', {
    type: 'entity'
});

// initialize code called once per entity
PlayerCameraMove.prototype.initialize = function() {
    this.force = new pc.Vec3();
    this.eulers = new pc.Vec3();
    
    this.jumping = {
        state: false
    };
    
    
    var app = this.app;
    
    // Listen for mouse move events
    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");
    }
};

// update code called every frame
PlayerCameraMove.prototype.update = function(dt) {
    // If a camera isn't assigned from the Editor, create one
    if (!this.camera) {
        this._createCamera();
    }
    
    
    var force = this.force;
    var app = this.app;

    // Get camera directions to determine movement directions
    var forward = this.camera.forward;
    var right = this.camera.right;
       

    // movement
    var x = 0;
    var z = 0;

    // Use W-A-S-D keys to move player
    // Check for key presses
    if (app.keyboard.isPressed(pc.KEY_A)) {
        x -= right.x;
        z -= right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_D)) {
        x += right.x;
        z += right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_W)) {
        x += forward.x;
        z += forward.z;
    }

    if (app.keyboard.isPressed(pc.KEY_S)) {
        x -= forward.x;
        z -= forward.z;
    }

    // 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);
    }
    
    if (app.keyboard.wasPressed(pc.KEY_SPACE)) {
        if (this.jumping.state === false) {
            this.entity.rigidbody.applyImpulse(0, this.jumpPower, 0);
            this.jumping.state = true;
        }
    } else if (this.jumping.state === true) {
        // If the raycast finds a collision, we assume it is an obect we can land on, we therefor reset our jump state so we can jump again.
        if (this._checkBelow() !== null) {
            this.jumping.state = false;
        }
    }

    // update camera angle from mouse events
    this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0);
    //not sure if it works
    this.hitbox.setLocalEulerAngles(0, this.eulers.x, 0);
    
    this.eulers.y = pc.math.clamp(this.eulers.y, -80, 80);
    this.eulers.x = pc.math.clamp(this.eulers.x, -80, 80);
};

PlayerCameraMove.prototype._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;
    }            
};

PlayerCameraMove.prototype._checkBelow = function() {
    return this.app.systems.rigidbody.raycastFirst(this.entity.getPosition(), this.raycastPlayerBase.getPosition());
};

PlayerCameraMove.prototype._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, 0.5, 0);
};

updated code with the line. According the library or docs (which one is it called?) It says that I am doing it right. Am i missing defining it somewhere in the code it needs to be?

1 Like

You use this.hitbox instead of this.hitBox.

ok I put into the intialize var hitbox = this.hitbox and changed this line

this.hitbox.setLocalEulerAngles(0, this.eulers.x, 0);

but i still get the error, i save and parse and then run and i still get
[PlayerCameraMove.js?id=43975171&branchId=abf7dc27-cf14-4fa2-907d-bd028a23c7ed:127]: Cannot read property ‘setLocalEulerAngles’ of undefined

I don’t understand how they are undefined.

I don’t see this line in your initialize function.

Sorry! i fixed it.

var PlayerCameraMove = pc.createScript('PlayerCameraMove');

PlayerCameraMove.attributes.add('camera', {
    type: 'entity',
    description: 'Optional, assign a camera entity, otherwise one is created'
});

PlayerCameraMove.attributes.add('power', {
    type: 'number',
    default: 2500,
    description: 'Adjusts the speed of player movement'
});

PlayerCameraMove.attributes.add('lookSpeed', {
    type: 'number',
    default: 0.25,
    description: 'Adjusts the sensitivity of looking'
});

PlayerCameraMove.attributes.add('jumpPower', {
    type: 'number',
    default: 200.0
});

PlayerCameraMove.attributes.add('raycastPlayerBase', {
    type: 'entity'
});

PlayerCameraMove.attributes.add('hitBox', {
    type: 'entity'
});

// initialize code called once per entity
PlayerCameraMove.prototype.initialize = function() {
    this.force = new pc.Vec3();
    this.eulers = new pc.Vec3();
    
    this.jumping = {
        state: false
    };
    
    var hitbox = this.hitbox;
    
    var app = this.app;
    
    // Listen for mouse move events
    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");
    }
};

// update code called every frame
PlayerCameraMove.prototype.update = function(dt) {
    // If a camera isn't assigned from the Editor, create one
    if (!this.camera) {
        this._createCamera();
    }
    
    
    var force = this.force;
    var app = this.app;

    // Get camera directions to determine movement directions
    var forward = this.camera.forward;
    var right = this.camera.right;
       

    // movement
    var x = 0;
    var z = 0;

    // Use W-A-S-D keys to move player
    // Check for key presses
    if (app.keyboard.isPressed(pc.KEY_A)) {
        x -= right.x;
        z -= right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_D)) {
        x += right.x;
        z += right.z;
    }

    if (app.keyboard.isPressed(pc.KEY_W)) {
        x += forward.x;
        z += forward.z;
    }

    if (app.keyboard.isPressed(pc.KEY_S)) {
        x -= forward.x;
        z -= forward.z;
    }

    // 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);
    }
    
    if (app.keyboard.wasPressed(pc.KEY_SPACE)) {
        if (this.jumping.state === false) {
            this.entity.rigidbody.applyImpulse(0, this.jumpPower, 0);
            this.jumping.state = true;
        }
    } else if (this.jumping.state === true) {
        // If the raycast finds a collision, we assume it is an obect we can land on, we therefor reset our jump state so we can jump again.
        if (this._checkBelow() !== null) {
            this.jumping.state = false;
        }
    }

    // update camera angle from mouse events
    this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0);
    //not sure if it works
    this.hitbox.setLocalEulerAngles(0, this.eulers.x, 0);
    
    this.eulers.y = pc.math.clamp(this.eulers.y, -80, 80);
    this.eulers.x = pc.math.clamp(this.eulers.x, -80, 80);
};

PlayerCameraMove.prototype._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;
    }            
};

PlayerCameraMove.prototype._checkBelow = function() {
    return this.app.systems.rigidbody.raycastFirst(this.entity.getPosition(), this.raycastPlayerBase.getPosition());
};

PlayerCameraMove.prototype._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, 0.5, 0);
};

The line is still not correct.

I genuinely don’t understand why?

I looked at your script and you are getting an error because:

PlayerCameraMove.attributes.add('hitBox', {
    type: 'entity'
});

it should be hitbox not hitBox then re-parse

1 Like

Ohhh shoot ok my bad, i changed that. Now the error says Cannot read property ‘setLocalEulerAngles’ of null.

Hmm so somehow now it’s null xD?

1 Like

Because you have two problems in your script. One problem is using capital letter or not and the other problem is using .this or not. Both problems are also mixed together.

1 Like