Unity Rigidbody Movement

Rigidbody Character Movement





Welcome, In this article, I'll teach you how to create a character controller using rigid bodies. Firstly, we'll set up our player's character by creating a simple one and give some very basic movement scripts with rigid body movement. Last time, we used the character controller one which was not physics-based. But, rigid body movement is a totally physics-based movement. In my view, it is easier than the character controller component.

#1 Rigid body and how to add it :

So, now we'll learn about rigid bodies. What exactly is a rigid body? Well, it is a built-in component in unity that applies physics in your Game Object. If u have a Game Object without a rigid body and you put in at a certain height then it won't fall. But, when you put rigid body gravity starts to be applied and that means it'll fall. so how do you add it? Simple just select the object you want to add it into and then click add component then select the rigid body component the same as in figure 4.1.

*We won't use character models since the player won't be seeing those we'll use a capsule only.

figure 4.1

#2 Rigidbody character Controller:

 So to create the character controller we'll create and add a character controller script which, most of you may know how to. If you don't know how to create and add a script then, click this. So now we've created and added a script let's code so last time I just gave you the code which wasn't very good. So, to make it better from now I'll break code into parts and explain them.

Variables.

We'll see all the variables in the code and I'll explain each of their purposes. Here are the variables:

[HideInInspector]
public Rigidbody _rigidbody;
public float speed, sensitivity,xsensitivity,jumpforce;
Vector2 xmove, ymove, velocity;
public Camera cam;
float yRot , xRot,mouseY;
public bool IsGrounded;
public float groundist;

[SerializeField]
float min, max;

So let's understand about each of them,

  • [HideInInsepctor]: It hides the rigid body so that we can't see it in our inspector.
  • _rigidbody: Here we're getting the rigidbody component to use for movement.
  • speed, sensitivity, xsensitivity, jumpforce: We are taking some float values here to control player speed camera horizontal sensitivity, camera vertical sensitivity, and jump force.
  • xmove, ymove, velocity: the Vector2 xmove and ymove are used to store transform.forward and transform.right 's x and z. We are doing this so that we can change the direction of the player after we rotate it. The velocity reference is used to store the normalized (I'll explain it soon) value of xmove and ymove combined.
  • cam: Here we take the camera of our player which we'll use to rotate and aim.
  • yRot, xRot, mouseY: We use xRot and yRot to store the value we get from our mouse.
  • [SerializeField]: It is used to show private variables on the inspector.
  • min, max: We use min and max to store how far cameras can rotate vertically.
  • others will be explained gradually.

Start() function:

After declaring the variables don't forget the start function it is required for our script. A start function initializes as soon as the game is started but, it doesn't loop like the Update() function. Here's the start code:

void Start()
{
_rigidbody= GetComponent<Rigidbody>();
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
initailspeed = speed;
}

At first, we have assigned the variable _rigidbody as the rigidbody component. Then, we locked and hid the cursor so that it looks good. Then, we assigned initialspeed as our speed because we'll be needing it for our sprint.

FixedUpdate() function:

private void FixedUpdate()
{
Rotate();
Move();
Jump();
}

Here we have used Unity's predefined function FixedUpdate() and we have up our own Move() and Rotate() functions here. So why did we do this? and what exactly is a fixed Update() function? An Update() function runs once per frame but the FixedUpdate() function may run zero, or several times in a single frame which makes it good for doing work related to physics. Our Move() and Rotate() functions contains physics-based movement and rotation which will be smoother on FixedUpdate() function. But on our CameraLook() function (You'll see it soon) contains the camera rotation and no physics so we kept it on the Update() function.

Move() Function:

So we now create a function for moving our player and name it Move().

void Move()
{
}

Now we assign some values to our Vector 2s, the values to x and y.

void Move()
{
xmove = new Vector2( Input.GetAxisRaw("Horizontal") * transform.right.x,
Input.GetAxis("Horizontal")* transform.right.z);

ymove = new Vector2( Input.GetAxisRaw("Vertical") * transform.forward.x,
Input.GetAxis("Vertical")* transform.forward.z);

}

Here on xmove, we took Horizontal axes from our keyboard which are a and d or right and left, and on ymove, we took Vertical axes which are w and s or up and down. As you can see we multiplied the axes with transform.right.x and transform.right.z or transform.forward.x and transform.forward.z. We did this so that we could move in the corner which is at the center of z and x-axes (Figure 4.2) which helps us to change the direction of movement when the player rotates.

Figure 4.2

So, as you see in the figure (which was just an example) our player also will be able to calculate that but with x * z, z*z, and x*x  and store it to the y-axis of xmove / ymove. It changes the direction of the player when we rotate it.

Now, we normalize the xmove and ymove apply speed to it then we move the character.

velocity = (xmove+ymove).normalized*speed*Time.deltaTime;
_rigidbody.velocity = new Vector3(velocity.x,_rigidbody.velocity.y,velocity.y);

So, here you combine the xmove and ymove then we use the ().normalize keyword which gives the value in the magnitude of 1. After that, we multiply it with our speed variable and unity Time.deltaTime which helps smooth the movement making it less choppy.

Player Rotation and Camera Rotation:

Now, we'll rotate the player when the mouse is moved horizontally, also known as X-axis, and move the camera when the mouse is moved vertically, also known as the y-axis. We'll do the player rotation on the FixedUpdate() function but we'll do the camera rotation on the Update() function because we'll rotate the player using rigidbody.rotation which is physics-based.

So we'll do the player rotation at first.

private void FixedUpdate()
{
Rotate();
}

We'll do the Rotation code in Rotate() function, create the function and execute it via FixedUpdate() function.

void Rotate()
{
yRot = Input.GetAxis("Mouse X")*sensitivity;
_rigidbody.rotation *= Quaternion.Euler(0,yRot*Time.deltaTime,0);
}

Firstly, we have assigned the predefined axis "Mouse X" which takes our mouse's horizontal movement and we multiply it with sensitivity, which determines the speed of camera rotation. Then we apply the rotation by multiplying the rigidbody rotation with the yRot, which is now affected by time and the value will be the new rotation value of the player's rigidbody.

Now, we'll do the camera rotation. Since it doesn't use physics execute it from the Update() function.

void Update()
{
CameraLook();
}

Name the function as CameraLook().

void CameraLook()
{
xRot += -Input.GetAxis("Mouse Y") * xsensitivity;
xRot = Mathf.Clamp(xRot ,-min, max);
cam.transform.localRotation = Quaternion.Euler(xRot, 0, 0);
}

Firstly we assigned Mouse's vertical value multiplied by xsensitivity, the reason we used different values for vertical rotation of the camera because if we use the same value for sensitivity then the camera will be too fast while rotating vertically. Then we limited the camera's rotation so that camera doesn't rotate 360 degrees. Then finally, we rotate the camera.

Player Jumping:

Now we will do the player jumping we'll only jump if the player's on the ground so that player won't jump infinitely. To do that we'll use Raycast, which means casting a ray which returns true if it hits a physical gameobject. A raycast can be hit in any direction. It's used for functions like showing GUI like 'E to pick up when the player looks at a gameObject', shooting, etc. We'll execute the jump script on FixedUpdate() function because it is done with physics like adding force and Raycast also comes under physics.

private void FixedUpdate()
{
Jump();
}

Create a function and name it 'Jump'.

void Jump()
{
IsGrounded = Physics.Raycast(transform.position,Vector3.down,groundist);
if(Input.GetKeyDown(KeyCode.Space)&&IsGrounded)
{
_rigidbody.AddForce(new Vector3(0,jumpforce,0));
}
}
So we'll assign IsGrounded by hitting Raycast down and checking if the ground is in Range or not, if it is in range then IsGrounded is true. Then if the player is pressing space and the character is grounded then the player will jump or it won't jump. We are jumping using Rigidbody.AddForce() which is physics-based it is less likely used for shooting mechanics because instantiating too many rigid bodies causes lag.

Player Sprinting

In many games, there is sprinting mechanics so we will add it in our game too. It's very simple we'll execute via the Update() function since it doesn't contain any physics.

void Update()
{
if(Input.GetKeyDown(KeyCode.LeftShift))
{
Sprint();
}
if(Input.GetKeyUp(KeyCode.LeftShift))
{
speed = initailspeed;
}
}

Now, let's create the sprint function,

void Sprint()
{
speed = sprintspeed;
}

Here we check if the player presses the left shift and on the button press, we set speed's value as sprintspeed 's value after the player releases the key then we'll set is to back as it was. We got it's the first value because we assigned it to initialspeed at the start function.

Recommended values:


These are the values I recommend for the variables.

The Conclusion

We learned how to create a First-Person Character using a rigidbody for our Tower defense game. If you want to download the code or project files(after the project is finished) then be my PATREON. You can test how much you learned by taking this TEST.

Comments

Popular posts from this blog

First Person Movement in Unity

How To Make A Game