Balloon Physics for Meta Quest 3

I am continuing my experiments with Unity and the Meta Quest 3. I have been working on a balloon physics game. I have been able to get the to (sort of) mimic a downward float of a balloon that is losing its helium. I have been able to get the collisons with the game controller working as well, but the physics is not quite where I would like that to be either.

A blue sphere in a dining room with VR boundary lines

I definitely have some work to do on figuring out the physics for the balloon, but I am happy with the progress that I have made so far.


A blue sphere in a dining room with VR boundary lines


The big challenge I am working through right now is trying to figure out a good workflow for development. It is cumbersome to have to put on the headset every time I want to test something. I am looking into ways to make the development process more efficient. There are tools out there such as MQDH that I am looking into as well as the Meta XR Simulator. I am looking forward to trying these out and seeing how they can help me in my development process.

As far as the XR All-in-One Toolkit, I am finding it pretty easy to use. I have been able to get the basic interactions working pretty easily and the prefabs that are available have been pretty drag and drop. I am looking forward to getting more into the XR Toolkit and seeing what else I can do with it for Meta Quest 3 development.

I am continuing to also learn the passthrough mechanics for the Meta Quest 3. I really think that this is going to be a big part of the future of VR, especially with the Apple Vision Pro coming out. The idea that you don’t have to fully be immersed in a VR world is a big stepping stone I think for more mass adoption. I don’t think it will be too long before we start seeing more and more headsets/glasses out in public.

Here are some code snippets that I have been working on for the balloon physics.

You need to make sure your balloon has a Rigidbody and a Sphere Collider and that all of your controllers have a Rigidbody and a Sphere Collider as well. For instructions on how to set all of that up, I found a great tutorial on YouTube by Valem Tutorials that has been a great starting point for me. Make sure to start with this one: How to Make a VR Game in Unity and follow along to set up the environment, controllers, and get started with an object that you can interact with. I started with those tutorials and then started working on the balloon physics once I got an idea of how to set up the environment and controllers.

Balloon Float Script


using UnityEngine;

public class BalloonDescentBehavior : MonoBehaviour
{
    public float descentStrength = 0.2f; // Adjust this to control the descent speed
    public float movementRandomness = 0.1f; // Adjust this for wobble effect
    private Rigidbody rb;
    private bool recentlyHit = false; // Flag to indicate if the balloon was recently hit
    private float hitPauseDuration = 2f; // Time in seconds to pause descent after being hit
    private float hitTimer = 0f; // Timer to track pause duration

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        if (rb == null)
        {
            Debug.LogError("BalloonDescentBehavior script requires a Rigidbody component to work.");
            return;
        }

        rb.useGravity = false;
    }

    void FixedUpdate()
    {
        if (recentlyHit)
        {
            hitTimer += Time.fixedDeltaTime;
            if (hitTimer >= hitPauseDuration)
            {
                // Reset flag and timer after pause duration has elapsed
                recentlyHit = false;
                hitTimer = 0f;
            }
        }
        else
        {
            ApplyDescentForce();
        }
    }

    void ApplyDescentForce()
    {
        // Simulate controlled descent by applying a gentle downward force
        Vector3 descentForce = -Vector3.up * descentStrength;
        descentForce.x += Random.Range(-movementRandomness, movementRandomness);
        descentForce.z += Random.Range(-movementRandomness, movementRandomness);
        rb.AddForce(descentForce, ForceMode.Acceleration);
    }

    public void NotifyHit()
    {
        recentlyHit = true;
        hitTimer = 0f; // Reset the timer every time the balloon is hit
    }
}

Controller Interaction Script


using UnityEngine;

public class ControllerInteraction : MonoBehaviour
{
    public float hitMultiplier = 50f; // Adjust this to scale the force based on controller velocity
    public float upwardBonus = 5f; // Additional upward force to apply when hitting from below

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Balloon"))
        {
            Rigidbody balloonRigidbody = collision.gameObject.GetComponent<Rigidbody>();
            if (balloonRigidbody != null && collision.rigidbody != null)
            {
                // Use the velocity of the controller to calculate hit force
                Vector3 controllerVelocity = collision.rigidbody.velocity;
                float hitStrength = controllerVelocity.magnitude * hitMultiplier;

                // Calculate hit direction
                Vector3 hitDirection = collision.contacts[0].point - transform.position;
                hitDirection = -hitDirection.normalized; // Consider adjusting this based on desired behavior

                // Add more "upwardness" for hits from below
                if (hitDirection.y > 0)
                {
                    hitDirection += Vector3.up * upwardBonus;
                }

                // Apply dynamic force based on controller speed and direction
                balloonRigidbody.AddForce(hitDirection * hitStrength, ForceMode.Impulse);
            }

            // Notify the BalloonDescentBehavior script that the balloon was hit
            BalloonDescentBehavior balloonBehavior = collision.gameObject.GetComponent<BalloonDescentBehavior>();
            if (balloonBehavior != null)
            {
                balloonBehavior.NotifyHit();
            }
        }
    }
}