- Home /
How would I make a rigidbody object climb a wall?
I'm fairly new at Unity and still learning scripting so there's a lot I might be missing here, but I'm making a 2D game using multiple characters that move by themselves. Therefore I need to program them to behave in certain ways when they interact with certain objects. So far all I've been able to accomplish is getting them to start walking when they touch the ground (using a raycast).
My next challenge is getting them to climb when they collide with a "tree trunk". I can get the object to recognize that it's touching a tree trunk and it looks like it's attempting to move up, but something is stopping it and I'm not sure why. Any help would be appreciated. Here is the code I have so far:
var moveSpeed = 5; var distToGround : float; var squirrelDirection : boolean; var climbSpeed = 5;
function Start() {
//get the distance to the ground
distToGround = collider.bounds.extents.y;
}
//Checks distance to ground
function IsGrounded(): boolean {
return Physics.Raycast(transform.position, -Vector3.up, distToGround + 0.1);
}
function Update() {
//Starts squirrel moving to the right when it touches the ground
if(IsGrounded() && squirrelDirection == false)
{
//moves squirrel to the right
transform.Translate(Vector3.right * moveSpeed * Time.deltaTime);
}
if(IsGrounded() && squirrelDirection == true)
{
//moves squirrel to the left
transform.Translate(Vector3.left * moveSpeed * Time.deltaTime);
}
}
//Clicking on a squirrel changes its direction
function OnMouseDown() { if(squirrelDirection == false) { squirrelDirection = true; }
else if(squirrelDirection == true)
{
squirrelDirection = false;
}
}
//This is where I'm having the problem
//Climbing function
function OnCollisionEnter ( other : Collision) {
if(other.gameObject.CompareTag("treeTrunk"))
{
var normal = other.contacts[0].normal;
if(normal.x > 0)
{
useGravity = false;
transform.Translate(Vector3.up * climbSpeed * Time.deltaTime);
Debug.Log("Touching tree trunk");
}
}
}
OnCollisionEnter is only called once on entry/reentry. What you should do is create is an "IsClimbing" boolean that, if true, sets the direction translate should go when moving forward (unless you have a specific key just for climbing. OnCollisionEnter sets IsClimbing to true, OnCollisionExit sets IsClimbing to false.
Thank you for your response. I set up an isClimbing boolean and had it call an IsClimbing function that tells it what to do when isClimbing is true, but it still does the same thing as before. Since it tells the variable to be true when it touches the tree, it should continuously move up after that right? I'm not sure why it's not working now. Here is the new code I have now:
//Calls climbing function when touching treeTrunk
function OnCollisionEnter ( other : Collision) {
if(other.gameObject.CompareTag("treeTrunk"))
{
var normal = other.contacts[0].normal;
if(normal.x > 0)
{
isClimbing = true;
IsClimbing();
}
}
}
//Climbing function
function IsClimbing() {
if(isClimbing == true)
{
useGravity = false;
transform.Translate(Vector3.up * climbSpeed * Time.deltaTime);
Debug.Log("Touching tree trunk");
}
}
See my answer below. The issue is that IsClimbing
, the function, is only called once.
Thanks. Your suggestion seems to work, however now there is another unexpected problem. When the rigidbody touches the wall it doesn't want to stay held against it. It continues to bounce off of the wall and the code only allows it to keep going up when it's touching the wall. Because of this, I tried use:
rigidbody.constraints = RigidbodyConstraints.FreezePositionY;
to hold it against the wall as it climbs, but that doesn't seem to work. When I put that in, it begins to climb the wall for a split second and then floats off into space and loses all position and rotation locks I have set on it. Is that the proper code to lock something along its vertical axis? I'm very confused by this. Thanks again for any help.
Answer by Jerdak · Jun 01, 2013 at 06:58 PM
Following up on my comment above, here is a quick hack that should get you close.
All I'm doing is turning isClimbing
true and false based on when the player collides w/ the tree and then exits that collision. The actual translate happens in Update(). You can see where I use isClimbing
in Update to determine both the direction and the speed of translation.
function OnCollisionEnter (other : Collision) {
if(other.gameObject.CompareTag("treeTrunk")){
var normal = other.contacts[0].normal;
if(normal.x > 0){
isClimbing = true;
}
}
}
function OnCollisionExit (other : Collision) {
if(other.gameObject.CompareTag("treeTrunk")){
isClimbing = false
}
}
function Update(){
var direction = (isClimbing)?Vector3.up:Vector3.forward;
var speed = (isClimbing)?climbingSpeed:moveSpeed;
// if 'squirrelDirection' is true, move right or up, else move down or left.
direction *= (squirrelDirection)?1:-1;
if(/*whatever input you use for movement is true*/)
transform.Translate(direction*speed*Time.deltaTime);
}
Your answer
Follow this Question
Related Questions
Any way to have a rigidbody not be affected by forces, but still collide with other objects? 2 Answers
ball's collider sometimes catches an edge and bounces. when ball rolls over two aligned platforms 1 Answer
Rigidbody MovePosition doesnt use continous dynamic setting 1 Answer
Avoid Player bouncing when colliding with objects 3D 1 Answer
Inconsistent collision detection on slow-moving objects 0 Answers