Remove Upward Vector from Velocity

Hello, I’m trying to make an obstacle in my game. It’s like the bumpers you get in Pinball machines. When the player touches it, it’s meant to bounce them off.

Getting that to work was easy enough, but I want it to be slightly biased into pushing them sideways, as opposed to upwards.

Here is my code:

   private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            Vector3 Direction = other.transform.position - Collider.transform.position;
            Direction = Direction.normalized;
            Vector3 Bias = Vector3.one - transform.up;
            Direction = Vector3.Lerp(Direction, Vector3.Scale(Direction, Bias), VerticalityBias);
            other.GetComponent<Rigidbody>().velocity = Direction * BounceForce;
        }
    }

As you can see, it’s a sphere, and the player gets pushed directly away from the center. But what I am trying to do, is make it so that, even if the player hit it near the top, it still tries to push them sideways.

I assumed I could take a “Vector3.one” and subtract its Upwards vector, then multiply the direction by that (Or lerp it for a milder effect) to essentially remove or minimize the upward force added to the player, making it so Vector Forward, and Vector Right have more of an influence.

Currently, the code here doesn’t do anything other than bounce with normal force in all directions. A Bias of 0 - 1, has no effect. I am unsure why this doesn’t work, but perhaps someone has another idea on how to calculate my “Bias” variable (The true force direction with the Up Vector masked out).

You’re on the right track, and as ever, there are a few ways of doing this, but here is one based on your existing code.

        Vector3 direction = other.transform.position - collider.transform.position;
        direction = direction.normalized;
        Vector3 flattenedDirection = direction;
        flattenedDirection.y = 0;
        direction = Vector3.Lerp(direction, flattenedDirection, verticalityBias);
        other.GetComponent<Rigidbody>().velocity = direction * bounceForce;

Rather than doing anything with scaling, I’ve made a copy of “direction” and then set its y to 0, and then you can lerp between those two vectors in the same way.


Small nitpick while I’m here, its best practice to make sure your variable names start lowercase, as it quickly gets confusing trying to tell if “Collider” is the class, or an object with that name, so I’ve renamed them in my example.


edit: Fix for removing RELATIVE up

Meet your new friend: Vector3.Dot() It lets you get the magnitude of a component of a vector that is in a particular direction:

Vector3.Dot(direction, transform.up)

Gives us the scale of the direction vector, but only the part of it in the direction of transform up.
So then if we multiply that by transform up we get the unwanted component of our direction vector:

Vector3 unwantedDirection = Vector3.Dot(direction, transform.up) * transform.up;

So then to get our new version of flattenedDirection we subtract that from the total direction:

Vector3 flattenedDirection = direction - unwantedDirection;

So this is what we end up with now:

        Vector3 direction = other.transform.position - collider.transform.position;
        direction = direction.normalized;
        float upwardMagnitude = Vector3.Dot(direction, transform.up);
        Vector3 unwantedDirection = Vector3.Dot(direction, transform.up) * transform.up;
        Vector3 flattenedDirection = direction - unwantedDirection;
        direction = Vector3.Lerp(direction, flattenedDirection, verticalityBias);
        other.GetComponent<Rigidbody>().velocity = direction * bounceForce;