- Home /
The question is answered, right answer was accepted
My player passes through walls
Hi, In doing simple test to study unity and now I'm have a problem with my character not colliding with obstacles an passing through them. The concept is simple: player walks, and there are objects with a rotation code and you have to wait the right space to pass but my player passes trought the obstacles... I'm new on learning Unity It would be great If you could help me. I have the impresion is for the transfom.position but I don't know other ways to move a character (evrything has colliders) Movement code:
public int speed;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
{
//Movement
Vector3 newPosition = this.transform.position + (Time.deltaTime * this.speed * new Vector3(1.0f, 0.0f, 0.0f));
this.transform.position = newPosition;
//flip
transform.localScale = new Vector3(-1.0f, 1.0f, 1.0f);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
//Movement
Vector3 newPosition = this.transform.position + (Time.deltaTime * this.speed * new Vector3(-1.0f, 0.0f, 0.0f));
this.transform.position = newPosition;
//flip
transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
}
}
}
and rotation code:
public float speed;
public Vector3 Axis = Vector3.zero;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
this.transform.Rotate(this.Axis, this.speed * Time.deltaTime);
}
}
Answer by TyDoesStuff · Sep 12, 2017 at 01:10 AM
Okay, building off of what the other two responses are, here is what you need to do / know. Number one could just solve your problem but I think you would benefit from looking at number three.
1) Unity uses a system where you add components to objects. If you add a "Collider" or "Collider 2D" this should stop any translations from passing through other game objects with the collider component. Try adding a collider to both your player and walls.
2) The way you have designed everything else so far might conflict with the above. Only do this option if the above DID NOT WORK. You may try setting up an algorithm that can detect what area should not be accessible. Detect when the player enters that zone and set the forward velocity to 0. This way would take much more time, more than what a beginning project should take.
3) Another option would be to lock the rotation of the rigidbody component and just apply a force to that. Here is an example I programmed: (C#)
// Change this to whatever speed you find appropiate.
// Remember that really high speeds may allow your character to clip through walls
private float maxSpeed = 10f;
void Start()
{
// Creates the rigidbody2D component
// (I am assuming your project is 2D, if not just remove the "2D")
rigidbody = gameObject.GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
// Much more efficient than creating your own input
float move = Input.GetAxis("Horizontal");
// Generates the thrust forward to your rigidbody
rigidbody.velocity = new Vector2(move * maxSpeed, rigidbody.velocity.y);
}
I really hope this can help you understand Unity a bit more. Tell me if there was anything I was unclear about. Happy programming!
-Ty
I am so glad to help! I know what it feels like starting out with Unity. The code snippet I added is something I used for my own game. :3 Also I haven't tried this yet but I think for when you flip your players direction you can do something much simpler: if you look at your player in the editor, you will see a "flip" check box in the sprite renderer. $$anonymous$$aybe you could look into altering that ins$$anonymous$$d? Anyways, enjoy yourself!
-Ty
Answer by lilinjie_ · Sep 12, 2017 at 03:04 PM
Adding a Rigidbody
component to an object will put its motion under the control of Unity's physics engine. Even without adding any code, a Rigidbody
object will be pulled downward by gravity and will react to collisions with incoming objects if the right Collider component is also present.
The Rigidbody also has a scripting API that lets you apply forces to the object and control it in a physically realistic way. For example, a car's behavior can be specified in terms of the forces applied by the wheels. Given this information, the physics engine can handle most other aspects of the car's motion, so it will accelerate realistically and respond correctly to collisions.
In a script, the FixedUpdate
function is recommended as the place to apply forces and change Rigidbody
settings (as opposed to Update
, which is used for most other frame update tasks). The reason for this is that physics updates are carried out in measured time steps that don't coincide with the frame update. FixedUpdate
is called immediately before each physics update and so any changes made there will be processed directly.
Reference: https://docs.unity3d.com/ScriptReference/Rigidbody.html
A CharacterController
allows you to easily do movement constrained by collisions without having to deal with rigibody. A CharacterController is not affected by forces and will only move when you call the Move function. It will carry out the movement but be constrained by collisions.
Reference: https://docs.unity3d.com/ScriptReference/CharacterController.html
Move use position
Didn't react to collision even have Rigidbody component.
public class PositionMove : MonoBehaviour
{
public float speed;
void Update()
{
float deltaX = Input.GetAxis( "Horizontal" ) * speed;
float deltaZ = Input.GetAxis( "Vertical" ) * speed;
Vector3 movement = new Vector3( deltaX, 0, deltaZ );
// Returns a copy of vector with its magnitude clamped to maxLength
movement = Vector3.ClampMagnitude( movement, speed );
movement *= Time.deltaTime;
transform.position += movement;
}
}
Move use Translate
Didn't react to collision without Rigidbody component.
React to collision with Rigidbody, simulate physics.
public class TranslateMove : MonoBehaviour
{
public float speed;
void Update()
{
float deltaX = Input.GetAxis( "Horizontal" ) * speed;
float deltaZ = Input.GetAxis( "Vertical" ) * speed;
Vector3 movement = new Vector3( deltaX, 0, deltaZ );
// Returns a copy of vector with its magnitude clamped to maxLength
movement = Vector3.ClampMagnitude( movement, speed );
movement *= Time.deltaTime;
transform.Translate( movement );
}
}
Move use Rigidbody
React to collision, simulate physics.
[RequireComponent( typeof( Rigidbody ) )]
public class RigidbodyMove : MonoBehaviour
{
Rigidbody rb;
// set the value great 100
public float speed;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float deltaX = Input.GetAxis( "Horizontal" ) * speed;
float deltaZ = Input.GetAxis( "Vertical" ) * speed;
Vector3 movement = new Vector3( deltaX, 0, deltaZ );
// Returns a copy of vector with its magnitude clamped to maxLength
movement = Vector3.ClampMagnitude( movement, speed );
movement *= Time.deltaTime;
// Transforms direction from local space to world space.
movement = transform.TransformDirection( movement );
rb.AddForce( movement );
}
}
Move use CharacterController
React to collision, didn't simulate physics.
[RequireComponent( typeof( CharacterController) )]
public class CharacterMove : MonoBehaviour
{
CharacterController cc;
// set the value great 100
public float speed;
// Use this for initialization
void Start()
{
cc = GetComponent<CharacterController>();
}
void FixedUpdate()
{
float deltaX = Input.GetAxis( "Horizontal" ) * speed;
float deltaZ = Input.GetAxis( "Vertical" ) * speed;
Vector3 movement = new Vector3( deltaX, 0, deltaZ );
// Returns a copy of vector with its magnitude clamped to maxLength
movement = Vector3.ClampMagnitude( movement, speed );
movement *= Time.deltaTime;
// Transforms direction from local space to world space.
movement = transform.TransformDirection( movement );
cc.Move( movement );
}
}
Answer by FortisVenaliter · Sep 07, 2017 at 07:02 PM
Well, you haven't coded it to be blocked by the obstacles. That kind of logic doesn't just happen on it's own.
You need to (1) detect the collision, (2) respond to the collision by stopping the player's velocity in that direction, and (3) push the player out of the collision zone if necessary to prevent them from becoming stuck.
Answer by bolkay · Sep 12, 2017 at 09:29 AM
Make sure you have the collider component attached to the walls. You can experiment with different colliders to achieve your desired result.
Follow this Question
Related Questions
Tiled Movement Inputs are Inaccurate 1 Answer
coroutine in update method 1 Answer
Camera Movement Bounds? 1 Answer
Rigidbody Precise Colliders 1 Answer
Character Transform shifting after colliding with objects 0 Answers