PlayCanvas游戏开发:如何用Shift键实现角色加速并优化冗余代码
优化PlayCanvas第一人称移动脚本(Shift加速功能)
我是编程新手,正在使用PlayCanvas开发游戏,希望实现按下Shift键时提升角色移动速度。目前我已完成该功能,但代码较为冗余,现有实现代码如下,寻求更简洁的实现方法。
原始代码
var FirstPersonMovement = pc.createScript('firstPersonMovement'); FirstPersonMovement.attributes.add('camera', { type: 'entity', description: 'Optional, assign a camera entity, otherwise one is created' }); FirstPersonMovement.attributes.add('power', { type: 'number', default: 2500, description: 'Adjusts the speed of player movement' }); FirstPersonMovement.attributes.add('lookSpeed', { type: 'number', default: 0.25, description: 'Adjusts the sensitivity of looking' }); // initialize code called once per entity FirstPersonMovement.prototype.initialize = function() { this.force = new pc.Vec3(); this.eulers = new pc.Vec3(); 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 FirstPersonMovement.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 and SHIFT keys to move player // Check for key presses if (app.keyboard.isPressed(pc.KEY_A) || app.keyboard.isPressed(pc.KEY_Q)) { 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; } if (app.keyboard.isPressed(pc.KEY_SHIFT)) { 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); } // update camera angle from mouse events this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0); }; FirstPersonMovement.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; } }; FirstPersonMovement.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); };
优化后的代码
var FirstPersonMovement = pc.createScript('firstPersonMovement'); FirstPersonMovement.attributes.add('camera', { type: 'entity', description: '可选,指定相机实体,否则自动创建' }); FirstPersonMovement.attributes.add('power', { type: 'number', default: 2500, description: '调整玩家移动基础速度' }); FirstPersonMovement.attributes.add('lookSpeed', { type: 'number', default: 0.25, description: '调整视角灵敏度' }); FirstPersonMovement.attributes.add('sprintMultiplier', { type: 'number', default: 2, description: 'Shift冲刺时的速度倍率' }); // 初始化代码,每个实体调用一次 FirstPersonMovement.prototype.initialize = function() { this.force = new pc.Vec3(); this.eulers = new pc.Vec3(); const app = this.app; // 监听鼠标移动事件 app.mouse.on("mousemove", this._onMouseMove, this); // 点击鼠标时隐藏光标并锁定指针 app.mouse.on("mousedown", () => app.mouse.enablePointerLock(), this); // 检查必要组件是否存在 if (!this.entity.collision) { console.error("第一人称移动脚本需要绑定碰撞组件"); } if (!this.entity.rigidbody || this.entity.rigidbody.type !== pc.BODYTYPE_DYNAMIC) { console.error("第一人称移动脚本需要绑定动态刚体组件"); } }; // 每帧执行的更新代码 FirstPersonMovement.prototype.update = function(dt) { // 如果未指定相机,自动创建 if (!this.camera) { this._createCamera(); } const force = this.force; const app = this.app; const forward = this.camera.forward; const right = this.camera.right; // 计算基础移动方向 let x = 0; let z = 0; // 统一处理方向输入 x += (app.keyboard.isPressed(pc.KEY_D) - app.keyboard.isPressed(pc.KEY_A) - app.keyboard.isPressed(pc.KEY_Q)) * right.x; z += (app.keyboard.isPressed(pc.KEY_D) - app.keyboard.isPressed(pc.KEY_A) - app.keyboard.isPressed(pc.KEY_Q)) * right.z; x += (app.keyboard.isPressed(pc.KEY_W) - app.keyboard.isPressed(pc.KEY_S)) * forward.x; z += (app.keyboard.isPressed(pc.KEY_W) - app.keyboard.isPressed(pc.KEY_S)) * forward.z; // 应用冲刺倍率 const speedMultiplier = app.keyboard.isPressed(pc.KEY_SHIFT) ? this.sprintMultiplier : 1; // 仅当有移动输入时施加力 if (x !== 0 || z !== 0) { force.set(x, 0, z).normalize().scale(this.power * speedMultiplier); this.entity.rigidbody.applyForce(force); } // 更新相机视角 this.camera.setLocalEulerAngles(this.eulers.y, this.eulers.x, 0); }; FirstPersonMovement.prototype._onMouseMove = function (e) { // 指针锁定或按住左键时更新视角 if (pc.Mouse.isPointerLocked() || e.buttons[0]) { this.eulers.x -= this.lookSpeed * e.dx; this.eulers.y -= this.lookSpeed * e.dy; } }; FirstPersonMovement.prototype._createCamera = function () { // 自动创建第一人称相机 this.camera = new pc.Entity(); this.camera.setName("第一人称相机"); this.camera.addComponent("camera"); this.entity.addChild(this.camera); this.camera.translateLocal(0, 0.5, 0); };
优化说明
- 新增可配置冲刺倍率:添加
sprintMultiplier属性,无需硬编码冲刺速度,在编辑器中即可调整,灵活性更高。 - 简化按键判断逻辑:用
按键按下状态(0或1)相减的方式合并方向输入代码,减少重复的if判断。 - 修复Shift逻辑错误:原代码按下Shift会直接添加前进力(无论是否按W),优化后改为在当前移动方向基础上乘以倍率,符合正常冲刺逻辑。
- 精简代码结构:合并重复的
app.keyboard.isPressed调用,减少冗余代码;用箭头函数简化事件回调写法。 - 中文注释优化:将注释改为中文,更贴合新手阅读习惯。
内容的提问来源于stack exchange,提问作者Kyle_3_1415
相关产品推荐
相关产品推荐

