- Home /
Make player not go through walls
I'm using a very simple script but I'm trying to make it so my player cant phase through walls, any help is appreciated.
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
transform.position += Vector3.left; ;
}
if (Input.GetKeyDown(KeyCode.D))
{
transform.position += Vector3.right;
}
if (Input.GetKeyDown(KeyCode.Z))
{
transform.position += Vector3.up;
}
if (Input.GetKeyDown(KeyCode.S))
{
transform.position += Vector3.down;
}
}
Answer by tadadosi · Jun 20, 2020 at 08:24 PM
Hi! Your code is a great start to learn how to use inputs and how to move objects by using their transform component, but as you already noticed, it's no good when it comes to stop your objects from phasing through walls. The reason why this is happening it's because you aren't adding any extra code to check if your object is colliding with a wall or to add a limit to how far it can travel.
In order to stop this from happening, you could do several things, the easiest one is adding a rigidbody component to your gameobject in the Inspector tab and using the code I wrote to move your object. With this method you are using Unity's physics engine which will make all the collision calculations by itself, you just need to tell the rigidbody how to move without using transform.position or any other method that bypasses the rigidbody physics.
Edit: Added rotation towards moveInput to the script.
using UnityEngine;
public class RigidbodyTesting : MonoBehaviour
{
public float moveSpeed = 0.25f;
public float rotationRate = 15f;
public Transform target;
private Rigidbody _Rigidbody;
// Vector3 to store player inputs.
private Vector3 moveInput;
private void Awake()
{
// To store the component Rigidbody in the property _Rigidbody
// so that you can use it anywhere in your code.
TryGetComponent(out _Rigidbody);
}
private void Update()
{
/* To add values to the moveInput property you write "new Vector3 (x, y, z)" and fill those
values with the inputs that you would like to use. In my case I used for the X axis
Input.GetAxis("Horizontal") to get the input values from the default
keys A, D, Left Arrow and Right Arrow and for the Z axis Input.GetAxis("Vertical") to
get the default input values from the keys W, S, Up Arrow and Down Arrow.
*/
// Try to always get your player inputs in the Update method.
moveInput = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
}
private void FixedUpdate()
{
// Rigidbody actions are handled by Unity's physics engine, so you should always mess with
// rigidbody stuff inside FixedUpdate, this will guarantee consistent physics behaviour.
// After this you just simply use your rigidbody position with a += moveInput (like you did) and multiply
// that Vector3 by a property I called moveSpeed so that you can control how fast your object should move.
_Rigidbody.position += moveInput * moveSpeed;
// sqrMagnitude is a value that goes up when any of the buttons from moveInput are pressed,
// I added this check here to make sure that our object stays on the last registered rotation
// (just before the player released the buttons). If you want your object to return to a default
// rotation, remove this if condition.
if (moveInput.sqrMagnitude > 0)
{
// We create a Quaternion, the type of variable we use to represent rotations and
// we use Quaternion.LookRotation to look at our moveInput vector which always points
// towards the moving direction, and we say that we want to rotate the Vector3.up (Y axis).
Quaternion rotation = Quaternion.LookRotation(moveInput, Vector3.up);
// Then we pass that rotation to our Rigidbody rot using Quaternion.Lerp which is a method
// to interpolate between two quaternions by a given time. In our case we use as the first
// Quaternion the _Rigidbody.rotation and as a second Quaternion our previously calculated rotation,
// then we add time by writing Time.fixedDeltaTime (fixed cuz we are in the method FixedUpdate)
// and we multiply that by a rotationRate to make it go faster or slower.
_Rigidbody.rotation = Quaternion.Lerp(_Rigidbody.rotation, rotation, Time.fixedDeltaTime * rotationRate);
}
}
}
Make sure that the gameobject you want to move has this script attached, a rigidbody and a collider. Also make sure you have a gameobject below to act as a ground and some walls (all with colliders).
This is incredible, it's simply perfect. Thank you so much for adding the comments, they help a lot with understanding the code. I wish I had more points I could give you.
I wonder if you know of a way to rotate the character with the movement direction?
@$$anonymous$$onty$$anonymous$$omentum Np! Glad I could help! I just added the rotation part to the answer. Best of Luck :)
Answer by sylvainlugezec · Mar 24, 2021 at 04:36 PM
Hi ! Finaly I finded a solution whose works well to avoid players pass through walls !
At the moment, I am creating a 3D labyrinthe game and the player can move and run in first person. My main issue iswas that my character could run between walls and pass through it ! And in a labyrinthe game, it's very embarrasing ! So, this is my solution :
1) - Select all walls in the hierarchy (with "shift" or "control")
2) - Add a component on every walls (if you had selected all walls, just do it one time)
3) - Check if the box "IsTrigger" is unchecked to use the collisions and
not the triggers4) - Check the button "Edit Collider" to see all box colliders points
5) - The width of every wall's collider must be at the minimum superior or egal to the player's collider width (radius if it's acapsule collider)
6) - With the walls' box colliders points, adjust them so that they can be merged to their extremities
7) - Create a (right click in the "Project" > "Create" > "Physic Material")
8) - Put all parameters at 0 ("Dynamic Friction", "Static Friction", "Bounciness") and "Friction Combine" to "Minimum" and "Bounce Combine" to "Minimum". It's for avoid frictions between the player and walls and it may cause vibrations and may permit the player pass through walls.
9) - Put this in the (or other player's collider) in the parameter "Material" of the player
10) - The player must have a "Rigidbody" to collide with walls (and others elements). Check them parameters : "Mass : 1", "Drag : 0", "Angular Drag : 0.05", "Use Gravity : checked", "Is Kinematic : unchecked", "Interpolate : None", "Collision Detection : Discrete", "Constraints Freeze Position : all unchecked", "Constraints Freeze Rotation : all checked"
/::: if "Is Kinematic" is checked, the player will pass through all elements, if "Interpolate" is not egal to "None", when the player will collide, there will be a little shift of the position, we block all "freeze rotation" (x,y,z), because it's avoid the player fall when he collide with an element :::/
11) - In C# in the player's script :
***
/*::: We use "FixedUpdate" and not "Update", because for the displacements of the player, the
"FixedUpdate" is better to calculate more frames :::*/
private void FixedUpdate() {
transform.Translate(Vector3.right * 4f * Time.deltaTime * Input.GetAxis("Horizontal"));
if (Input.GetAxis("Vertical") != 0) {
transform.Translate(Vector3.forward * 3f * Time.deltaTime * Input.GetAxis("Vertical"));
} else {
if (Input.GetAxis("Vertical") < 0) {
transform.Translate(Vector3.forward * 3f * Time.deltaTime * Input.GetAxis("Vertical"));
}
}
}
That so, I hope this mini tutorial will be helpful for you ! I am just a gameplay programmer and it's possible that this solution not works well for you, but I don't find a good tutorial for avoid that player pass through walls, so I do it myself !
Answer by wewewu · Jun 20, 2020 at 04:05 PM
Use Rigidbody.MovePosition(rb.position + movement) instead.
Answer by adam_unity566 · Jun 21, 2020 at 07:37 PM
I'm sorry if this approach to the problem is out of the question but wouldn't it be easier to use box colliders?
Your answer
Follow this Question
Related Questions
Help with 2D point and click move script that will stop moving when it hits a wall 1 Answer
GameObject B does not collide with GameObject A 1 Answer
Stop or cancel movement if the player hits wall. 2 Answers
Smooth Collisions 2D 0 Answers
Moving a player smoothly without breaking collisions? 2 Answers