Sun_and_Moon_Digital
7 months agoMember
Flight Pen
Hello, I'm trying to recreate the flight pen mechanic from AltspaceVR. I want to grab the pen, press the trigger, and fly in the direction my hand is pointing. I'd like it to control speed as well, so the farther away the pen is (relative to the player) from the trigger point the faster they go.
Right now I can grab the object, but nothing happens when I pull the trigger unless I jump. If I do jump and then trigger, I get movement (Z-axis) at a constant speed set whenever I trigger. So if I pull it early in the jump I go up fast. At the top of jump, up slow. The down part of the jump, I go down slow, or down fast if it's at the end of the jump. I can steer with the thumbstick, but it's not responding to my hand direction like it should. Also, once I start flying, I don’t stop until I let go of the pen, releasing the trigger doesn’t end the motion.
import * as hz from 'horizon/core';
class FlightPen extends hz.Component<typeof FlightPen> {
private player!: hz.Player;
private isFlying: boolean = false;
private origin!: hz.Vec3;
start() {
// Required lifecycle method
}
preStart() {
this.connectCodeBlockEvent(this.entity, hz.CodeBlockEvents.OnGrabStart, this.onGrabStart.bind(this));
this.connectCodeBlockEvent(this.entity, hz.CodeBlockEvents.OnGrabEnd, this.onGrabEnd.bind(this));
this.connectCodeBlockEvent(this.entity, hz.CodeBlockEvents.OnIndexTriggerDown, this.onTriggerDown.bind(this));
this.connectCodeBlockEvent(this.entity, hz.CodeBlockEvents.OnIndexTriggerUp, this.onTriggerUp.bind(this));
this.connectLocalBroadcastEvent(hz.World.onPrePhysicsUpdate, this.onPrePhysicsUpdate.bind(this));
}
onGrabStart(isRightHand: boolean, player: hz.Player) {
this.player = player;
}
onGrabEnd(player: hz.Player) {
if (player.id === this.player?.id) {
this.isFlying = false;
this.player.gravity.set(9.81); // Turn gravity back on
this.player.velocity.set(hz.Vec3.zero);
}
}
onTriggerDown(player: hz.Player) {
if (player.id === this.player?.id) {
this.origin = this.entity.position.get();
this.isFlying = true;
this.player.gravity.set(0);
// Apply a small lift to get airborne if grounded
const velocity = this.player.velocity.get();
if (velocity.y === 0) {
this.player.velocity.set(new hz.Vec3(0, 0.1, 0));
}
}
}
onTriggerUp(player: hz.Player) {
if (player.id === this.player?.id) {
this.isFlying = false;
this.player.velocity.set(hz.Vec3.zero); //
}
}
onPrePhysicsUpdate(data: { deltaTime: number }) {
if (!this.isFlying || !this.player) return;
const current = this.entity.position.get();
const offset = current.sub(this.origin);
if (offset.magnitude() < 0.01) return;
const direction = offset.normalize();
const pitch = this.player.rightHand.rotation.get().toEuler(hz.EulerOrder.XYZ).x;
direction.y += Math.sin(pitch);
const speed = offset.magnitude() * 10;
const velocity = direction.normalize().mul(speed);
this.player.velocity.set(velocity);
}
}
hz.Component.register(FlightPen);