This will set a min and max position for the object and randomly select a position within those values. Once selected it will move that object towards that position and rotate the object to look at that position. This is done on update using lerp and slerp respectively.
I did test this and seems to be working towards your specifications. Note that you will have to place this on the object that is supposed to move and set the offset values in the inspector. The moving object will be in the center of the area you desire it to move on start.
import { Component, PropTypes, Vec3, World, Quaternion} from 'horizon/core';
class RandomMoveWithinArea extends Component<typeof RandomMoveWithinArea> {
static propsDefinition = {
xOffset: { type: PropTypes.Number, default: 0 },
yOffset: { type: PropTypes.Number, default: 0 },
zOffset: { type: PropTypes.Number, default: 0 },
moveSpeed: { type: PropTypes.Number, default: 1 },
};
private maxPos: Vec3 = new Vec3(0, 0, 0);
private minPos: Vec3 = new Vec3(0, 0, 0);
private startPosition: Vec3 = new Vec3(0, 0, 0);
private targetPosition: Vec3 = new Vec3(0, 0, 0);
private startTime: number = 0;
private elapsedTime: number = 0;
private duration: number = 10000;
private isMoving: boolean = false
start() {
this.connectLocalBroadcastEvent(World.onUpdate, (data) => { this.onUpdate(data.deltaTime); });
// set the max and min values based on the entities position at world start and its set offsets
this.maxPos = this.entity.position.get().add(new Vec3(this.props.xOffset, this.props.yOffset, this.props.zOffset));
this.minPos = this.entity.position.get().sub(new Vec3(this.props.xOffset, this.props.yOffset, this.props.zOffset));
this.ChangePosition();
}
onUpdate(deltaTime: number) {
// we only want this to run if the object is supposed to be moving
if (this.isMoving) {
const currentTime = Date.now();
this.elapsedTime = currentTime - this.startTime;
// if the object has been moving longer than the desired amount of time
if (this.elapsedTime >= this.duration) {
this.entity.position.set(this.targetPosition);
this.startPosition = this.entity.position.get();
this.isMoving = false;
this.elapsedTime = 0;
this.ChangePosition();
}
else {
let amount = (this.elapsedTime / this.duration) * deltaTime * this.props.moveSpeed;
this.startPosition = this.entity.position.get();
const currentPosition = Vec3.lerp(this.startPosition, this.targetPosition, amount);
this.entity.position.set(currentPosition);
// increase the amount for slerp so the object rotates faster than it moves
amount *= 10;
const startRot = this.entity.rotation.get();
const endRot = Quaternion.lookRotation(this.targetPosition.sub(this.entity.position.get()), this.entity.up.get());
this.entity.rotation.set(Quaternion.slerp(startRot, endRot, amount));
}
}
}
async ChangePosition() {
// set our new x, y, and z values
// NOTE: If both values are not negative or positive then it can give unwanted values
const x = Math.random() * (this.maxPos.x - this.minPos.x);
const y = Math.random() * (this.maxPos.y - this.minPos.y);
const z = Math.random() * (this.maxPos.z - this.minPos.z);
// set a new vector to the random x, y, and z values and set the entities position to the new vector
this.startTime = Date.now()
this.targetPosition = new Vec3(x, y, z);
this.isMoving = true;
}
}
Component.register(RandomMoveWithinArea);