- Home /
Horizontal gravity physics on 3d game
I'm a freshman in college majoring in Game Design, and for my programming class we are required to update a previous Maze project to allow two players.
My maze was too small for two players on one track, so I am making two mazes and rotating them to be where the "walls" would be. My problem now is making a player run along the walls with the same gravity horizontally as would be on the ground.
I added
GetComponent<Rigidbody>().AddForce(Vector2.left * 9.8f);
But this does nothing but allow me to roll alongside the bottom wall.
I've seen the answer to this on 2D games, but not yet on 3D. Thanks, Brandon.
How about Vector3.left??
You can modify Physics.gravity in code.
http://docs.unity3d.com/ScriptReference/Physics-gravity.html
Answer by Eno-Khaon · Oct 13, 2015 at 06:43 PM
As a baseline, the gravity in Unity is applied to rigidbodies something like this:
// C#
void FixedUpdate()
{
rigidbody.AddForce(Physics.gravity, ForceMode.Acceleration);
}
So, every physics update, the objects with rigidbodies are pushed in the direction of gravity (default Vector3(0, -9.81, 0)). ForceMode.Acceleration ignores the mass of the object while pushing it, as gravity naturally would, and scales it relative to the FixedUpdate() rate.
With this in mind, there are two possible ways to approach this:
1 - If your gameplay environment is limited to a single wall for all players, you can simply modify Physics.gravity in the editor or by script to push them in the same direction.
2 - If the players are separated and each need their own gravitational force applied, you'll want each to have their own script for customized gravity application.
As a simplified example of what would go into that:
// C#
public Vector3 gravityDirection; // The direction of gravity for the object this script is attached to
Rigidbody rb; // This just keeps things simple
void Start()
{
rb = gameObject.GetComponent<Rigidbody>();
rb.useGravity = false; // Don't use world gravity, since we're replacing that for this object.
}
void FixedUpdate()
{
rb.AddForce(gravityDirection, ForceMode.Acceleration);
}
I understand the gravityDirection would be a new Vector3() whose default y value is -9.81but I'm not sure what I'd make it if I wanted to flip the gravity to go along the wall. As in which value is for y.
Never$$anonymous$$d, I enabled it in the editor to pull me to the left with a -90 pull to the left, but it doesn't allow me to go up and down on the axes.
I'm using Input.getAxis("Horizontal") and ("Vertical") to move. Will this affect it?
The strength of gravity doesn't necessarily need to be significantly increased for what you're doing. -9.81 is simply there as a representation of Earth's gravitational pull of approximately 9.81 meters per second.
The gravitational force is simply dictated by the direction specified. If the value on the Y-axis is 0, gravity won't pull up or down.
That aside, there's no impact on using Input.GetAxis() for movement. You will, however, need to specify directions manually to feed into it. That can be done in numerous ways, where the key element for good gameplay is consistency.
As an example, let's assume you're effectively using a "top-down" camera for your view. A basic presentation for controls could be something like this:
Rigidbody rb;
public float speed;
// This is the camera watching the player
// It will be the basis to orient the controls
// (Currently set up to be drag-and-drop defined manually in the editor)
public Transform cam;
// This is where your current input will be held
Vector2 inputDirection;
// This is used to carry accurate control input from Update() to use it for accurate physics in FixedUpdate()
Vector3 worldInput;
void Start()
{
rb = gameObject.GetComponent<Rigidbody>();
}
void Update()
{
inputDirection = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if(inputDirection.sqr$$anonymous$$agnitude > 1)
{
// Don't let the player move faster diagonally than straight
inputDirection = inputDirection.normalized;
}
// This is where the controls are rebuilt to match the orientation of your camera directly.
// Any angle on the camera will require tweaks to change the exact input.
worldInput = (cam.right * inputDirection.x) + (cam.up * inputDirection.y);
}
void FixedUpdate()
{
rb.AddForce(worldInput * speed);
}
That should cover the gist of it. With that, your controls will be directly based on the exact orientation of your camera, so if the camera spins, so will the controls.
I tried this on my current game and a brand new project, and the gravity works, although the controls don't work unless you use both one of the left or right and up or down keys at the same time, and even then it goes very slowly, no matter the speed I set.
Sorry, I offered a simplified implementation in this case, so it's not multiplying the final input by any speed variable. I've edited my last comment to include a multiplier on the final AddForce().
That said, any further limitation on your movement speed would be a result of friction with the surface you're on at the time.
Thank you so much. I'm looking into how this works with your comments. You've been super helpful.