Had an interesting discussion with some of your about the need to ‘re-use’ pc.Vec3s and pc,Quats instead of constantly instantiating new ones. It made me think that my way of writing scripts in PlayCanvas may not be optimal and following best practices. I like to get your feedback on what I could change to improve performance, readability and composability. Here is a script I just wrote, it’s a simple implementation of the kinematic ‘arrive’ movement behavior. Looking forward to your feedback.
const KinematicArrive = pc.createScript('kinematicArrive');
KinematicArrive.steering = {
velocity: new pc.Vec3(),
rotation: new pc.Quat()
}
KinematicArrive.prototype.initialize = function() {
this.position = this.entity.getPosition();
this.target = this.position.clone();
this.targetOffset = new pc.Vec3(0, this.position.y, 0);
this.radius = 0.1;
this.timeToTarget = 0.5;
this.turnSpeed = 5;
this.maxSpeed = 10;
this.rb = this.entity.rigidbody;
// Listen to mouse raycast hit and set target
this.app.on('mouseHitPosition', function(targetPos: pc.Vec3) {
this.target.copy(targetPos.add(this.targetOffset));
}, this);
}
KinematicArrive.prototype.update = function(dt: number) {
this.setOrientation(this.getSteering(), dt);
}
KinematicArrive.prototype.getSteering = function() {
const steering = KinematicArrive.steering;
const position = this.position;
// get direction to the target
steering.velocity.sub2(this.target, this.entity.getPosition());
// check if in radius
if(steering.velocity.length() < this.radius) {
steering.velocity.copy(pc.Vec3.ZERO);
steering.rotation.copy(this.entity.getRotation());
return steering;
}
// we need to move target. get there in timeToTarget seconds
steering.velocity.scale(1/this.timeToTarget);
// limit speed to max
if(steering.velocity.length() > this.maxSpeed) {
steering.velocity.normalize();
steering.velocity.scale(this.maxSpeed);
}
// update the rotation to face target
steering.rotation.lookAt(position, this.target);
return steering;
}
KinematicArrive.prototype.setOrientation = function(steering: {velocity: pc.Vec3, rotation: pc.Quat}, dt: number) {
// update the player velocity
this.rb.linearVelocity = steering.velocity;
// Slowly update the rotation over the timeToTarget time
this.entity.setRotation(new pc.Quat().slerp(this.entity.getRotation(), steering.rotation, dt * this.turnSpeed));
}