Forum Discussion

Sun_and_Moon_Digital's avatar
7 months ago

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

  • eshakm.2024's avatar
    eshakm.2024
    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

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

  • 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.

    • "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.