cancel
Showing results for 
Search instead for 
Did you mean: 

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);
6 REPLIES 6

eshakm.2024
Community Manager
Community Manager

Hello , 

Thanks for the feedback and request. I have forwarded this request to be looked and see if we can assit you in this. I will reach back out if get any further updates on this. 

Thank You

Great, thank you.

FreakyChest
Member

Did you want gravity back on when you release trigger? If so you need to add that onTriggerUp (this.player.gravity.set(9.81);). 

FreakyChest
Member

It looks like you are getting speed by offset.magnitude of flightPen when the trigger was pressed and the current position of the flightPen. So the further you move the faster you move. I think it may work better if you get the position relative to the player on click. That way if its 1 to the left of player at trigger, and now you move 2 to left from player it will set player velocity to left. Unless I am missing something.

I'd like gravity back on when grip is released and that is working.

"It looks like you are getting speed by offset.magnitude of flightPen when the trigger was pressed and the current position of the flightPen. So the further you move the faster you move."  

Yes, I'm trying to get any movement related to flightPen position but that's not working right now.