- Home /
Multiple Colliders Issue
Hello,
I have a question I need answered asap.
So basically my script is used to tell if the player is grounded or not. I used a collider to tell if the collider is grounded. However, I have come into a problem. Since the cube can rotate, i need to have the collider on every edge. So heres my problem. When I am next to a wall, I can double jump, triple jump, quadripual jump, well keep jumping untill I get off the wall. I have made a temporary fix by telling my script to make all objects which have a certain tag ("notag") on them, to make the cube not able to count them as a collider and to make grounded = false when they touch. This did somewhat solver my problem but lets say my cube is next to the wall, then the cube wont be able to jump because grounded is off when touching the wall. I want to make this script as dynamic as it can be so please help me.
#pragma strict
var speed : float = 20;
var jump : float = 5000;
var grounded = false;
function Start () {
}
function OnCollisionStay2D(other : Collision2D) {
if(other.gameObject.tag == "notag") {
grounded = false;
}
else {
grounded = true;
}
}
//BUG FIX : When touching notag, the player cant jump at all. Need it to see that there is a zone the player can jump at.
function OnCollisionEnter2D(other : Collision2D) {
if(other.gameObject.tag == "notag"){
grounded = false;
}
else {
grounded = true;
}
}
//BUG FIX : When player has collided with two objects and one collision leaves, grounded is false.
function OnCollisionExit2D(other : Collision2D) {
grounded = false;
}
function Update () {
if(Input.GetKey("d")) {
rigidbody2D.AddForce (Vector2(1, 0) * speed);
//transform.Translate(Vector3.right * Time.deltaTime * 10);
}
if(Input.GetKey("a")) {
rigidbody2D.AddForce (Vector2(-1, 0)* speed);
//transform.Translate(Vector3(-speed,0,0) * Time.deltaTime);
//transform.Translate(Vector3.left * Time.deltaTime * 10);
}
if(Input.GetKeyDown("space")){
if(!GravitySwitch.isOn){
if(grounded){
rigidbody2D.AddForce (Vector2(0, 1) * jump);
}
}
if(GravitySwitch.isOn){
if(grounded){
rigidbody2D.AddForce (Vector2(0, -1.2) * jump);
}
}
}
if(Input.GetKey("q")){
rigidbody2D.AddTorque (7.5);
}
if(Input.GetKey("e")){
rigidbody2D.AddTorque (-7.5);
}
}
Answer by Invertex · Jan 10, 2014 at 02:15 AM
The way I approached this was with Linecast. And it allowed me to have many options for queueing different animation states, such as edge balance or slope detection.
First, for a single linecast, I create two Empty GameObjects, one is the Start Position of the Linecast, the other is the End Position. These two objects are children of my Player. For example, I'd have one Linecast for the right foot, or right side of my Player. The groundR_start object would be positioned within my player collider, on it's right edge, and the _end object would be place below my collider, but still aligned with the right edge. This would detect when only the bottom right of my collider is touching ground.
Then in the script I create a Transform variable for them:
private Transform groundCheckL_start;
private Transform groundCheckL_end;
private Transform groundCheckM_start;
private Transform groundCheckM_end;
private Transform groundCheckR_start;
private Transform groundCheckR_end;
//Also, Bool's to contain the result of these Linecast's.
public bool groundedL;
public bool groundedM;
public bool groundedR;
And then assign them:
Start(){
groundCheckL_start = transform.Find("groundL_start");
groundCheckL_end = transform.Find("groundL_end");
groundCheckM_start = transform.Find("groundM_start");
groundCheckM_end = transform.Find("groundM_end");
groundCheckR_start = transform.Find("groundR_start");
groundCheckR_end = transform.Find("groundR_end");
}
Now, in my Update() function, I can use Linecast to detect which one's are hitting "Ground".
groundedR = Physics2D.Linecast(groundCheckR_start.position, groundCheckR_end.position, 1 << LayerMask.NameToLayer("Ground"));
groundedM = Physics2D.Linecast(groundCheckM_start.position, groundCheckM_end.position, 1 << LayerMask.NameToLayer("Ground"));
groundedL = Physics2D.Linecast(groundCheckL_start.position, groundCheckL_end.position, 1 << LayerMask.NameToLayer("Ground"));
Then you can simply use these 3 Bool's to determine if you're allowed to do something, like Jump. If at least one of them = true, then you probably want to let the player jump. And if say only groundedR is true, the player would play the balancing animation.
http://docs.unity3d.com/Documentation/ScriptReference/Physics2D.Linecast.html
Josie, any updates? Were any of these answers acceptable for you?
Not really. I decided the best way to do this is to leave the box collider grounded on but also add on a raycast in the center of the cube so if it rotates its always pointing down. However, I did try to put three on the box (one on each side and one in the middle) but then if my cube rotated the raycasts would intercept each other all they would all be pointing down in the center. Is there some way to fix this?
I'm confused as to why they would intercept eachother, if they are children of your cube, then they should rotate around the cube's axis...
Here's a quick example I made: http://gyazo.com/17bc243739811730aeac2e6d1d5c4bb1.mp4
Cube rotates and rays move with it fine.
Answer by xwpedram_N · Jan 07, 2014 at 04:41 AM
Create a Collision for your ground and in ground OnCollisionEnter2D change your grounded = false and on OnCollisionExit2D change grounded = true .
Answer by UnbreakableOne · Jan 10, 2014 at 01:48 AM
Try casting rays that their length is like a block or a bit longer than a block size. For example, cast three rays, one from toe of your character through the ground, one from his middle and one from his back. Does this help?
I was thinking about using raycasts but how would I be able to do that with the cube being on its edge. Would I need to make a raycast for every side plus inbetween the sides.
What do you mean, on it's edge? Do you mean when going up/down slopes?
The rigidbody on it allows for full rotation so if it lands on its edge I need it to still be grounded.
The solution in my answer would still allow for that, as the Linecast extends a fair bit past the bottom right corner. So even if you were on an angle, one of the two ground Linecasts on either corner would still be hitting ground. You'd also know from the results that you were either on a ledge or tilted.
Your answer
Follow this Question
Related Questions
Script doesn't find other script 0 Answers
Collision timer help 1 Answer
Collision, change skybox in game 1 Answer
Have script detect which collider 2 Answers
Script crashes Unity 1 Answer