- Home /
Rigidbodies flying up in the air on collision
Hey guys!
I've got a little problem going on over here, and i can't seem to find a solution. I've been making a simple Animal-AI for pigs, who are wandering around in the bounds of a fence, so far so good. When an animal get's to close to the fence (detected via Raycast) it turns around 180 degrees and walks on. But the problem is: When two pigs walk into each other, one of them either starts spinning around in weird ways or flies up 30-50 metres in the air.
The pigs have a Rigidbody as well as a Caspule Collider (oriented in Z-Direction) attached to them, and they are getting moved by
transform.Translate(Vector3.forward * Time.deltaTime * 1.9f);
Can someone help with that?
T.i.a.
Answer by Owen-Reynolds · Sep 05, 2011 at 03:59 PM
transform.Translate
does a micro-teleport, as far as the physics engine is concerned. A little like Lancelot attacking in Monty Python's Holy Grail. The "physics speed" (`rigidbody.velocity`) is left as mostly 0. You never get a real collision, caused by the physics engine moving them. Instead they just suddenly overlap, and it gets confused.
Physics wants to bounce the pigs away at their flipped speeds. Often both pigs have a tiny amount of down speed from gravity, so it bounces them both up, or velocity is close enough to 0 so bouncing does nothing, giving the vibrate.
I noticed you grab the controller, but then don't use it:
CharacterController controller = GetComponent<CharacterController>();
transform.Translate(Vector3.forward * Time.deltaTime * 1.9f);
If you instead move with controller.Move(Vector3.forward * Time.deltaTime * 1.9f);
it should do the math for you. Translate and Move look similar, but Translate will gladly shove you through hills. Controller.Move
does a lot of collision and ground slope detection to shove you around solid objects.
Alternately, lose the CharacterController and work with physics. Change the move line to:
rigidbody.velocity = Vector3.forward * 1.9f;
There's no Time.deltaTime in there, since the units are meters/second. The physics engine will automatically apply T.DT each frame. You used rigidbody.AddForce
in Start, but can't use that here -- it would thrust your pigs like rockets like a game of bumpercars.
You might get some vigorous, un-pig-like bounces. Playing with the physics material bounciness could help that.
Answer by NellacKun · Sep 05, 2011 at 02:00 PM
Create a new layer called "Pig" Set the Layer of the Pigs prefab to "Pig". Go to Edit > Project Settings > Physics Make sure the checkbox in the Layer Collision Matrix is unchecked for pig-pig collision. That will disable collisions for the pigs
Enjoy
I actually don't want the pigs to walk "through" each other. If two pigs in real world collide, one of them doesn't fly 50 metres up in the air. It can't be that hard to transfer this beahviour into unity
I took the time to recreate this problem
$$anonymous$$y two models running into each other causes no upward movement at all. After about 15 seconds of vibrating into each other they eventually separate and go their different directions.
I tried all types of colliders to see if anything could be different. With the constraints locked and without. Can you post your code for the pigs?
here's a little video clip i recorded, so you can see what's going on on my screen ;) http://www.youtube.com/watch?v=2D$$anonymous$$RuoX4F2g
Have you tried making the colliders bigger? That's really wierd, try locking the rigidbody constraints for it's XYZ rotation.
Answer by mati12_14 · May 21, 2016 at 06:46 PM
I think the best way to prevent flying out is freezing contains in rigidbody. For example I freeze "z axel" and all things is ok. Unity physics is not ideal. Sorry for mistakes. English is not my native language
Answer by remoteplayfreak · Sep 05, 2011 at 02:29 PM
Thanks for helping me ;)
I've thought about the rotation a pig can make when starting movement could cause the other pigs getting pushed up or away.
Nevertheless, here's the code:
private List <string> anims = new List <string>();
public LayerMask checkLayers;
private float lastTime;
private float nextTime;
private int animNumber;
private bool rotate;
private bool turnAround;
private float rotationAmount;
private float rotationSpeed;
private float currentRotation;
private float t;
void Awake() {
rotate = false;
turnAround = false;
rotationAmount = 0.0f;
rotationSpeed = 0.0f;
currentRotation= 0.0f;
t = 0.0f;
anims.Add("WlObjPig_Idle");
anims.Add("WlObjPig_Walking");
lastTime = 0.0f;
nextTime = 0.0f;
rigidbody.AddForce(Vector3.up * 10);
}
void Update() {
checkForwardDistance();
Vector3 mypos = transform.eulerAngles;
mypos.z = 0;
transform.eulerAngles = mypos;
Rotate();
if(animNumber == 1){
CharacterController controller = GetComponent<CharacterController>();
transform.Translate(Vector3.forward * Time.deltaTime * 1.9f);
}
if(Time.time > lastTime + nextTime){
lastTime = Time.time;
nextTime = UnityEngine.Random.Range(1.0f, 5.0f);
animNumber = UnityEngine.Random.Range(0, 2);
animation.CrossFade(anims[animNumber], 0.2f);
if(animNumber == 1){
rotate = true;
rotationAmount = UnityEngine.Random.Range(-90.0f, 90.0f);
rotationSpeed = UnityEngine.Random.Range(0.01f, 0.05f);
currentRotation = transform.eulerAngles.y;
} else {
rotate = false;
}
}
}
void Rotate(){
if(t >= 1.0f){
t = 0.0f;
rotationAmount = 0.0f;
}
if(rotationAmount != 0.0f){
transform.eulerAngles = new Vector3(0.0f, Mathf.Lerp(currentRotation, currentRotation + rotationAmount, t), 0.0f);
t += rotationSpeed;
}
}
void checkForwardDistance(){
Vector3 rayStart = new Vector3(transform.position.x, transform.position.y + 1f, transform.position.z);
Debug.DrawRay(rayStart, transform.forward * 4f, Color.red);
if(Physics.Raycast(rayStart, transform.forward, 4.0f, checkLayers)){
Debug.Log(true);
nextTime = 2.0f;
animNumber = 1;
rotate = true;
rotationAmount = 180f;
rotationSpeed = 0.03f;
currentRotation = transform.eulerAngles.y;
turnAround = false;
animation.CrossFade(anims[animNumber], 0.2f);
}
}
That is really odd, using your script, the EXACT same thing happens as in my script. They just vibrate and separate. I'm sorry I couldn't recreate the problem. I checked your code and it seems fine.
What I do for my collision checks is I use 3 raycasts that fires rays forward, slightly left and slightly right, and attempts to move around any blocking or nearby objects. It's very simple object avoidance, and gets stuck in corners. :)
that would be really nice ;) that actually IS odd... i have tried locking all the rotation axes, but then the pigs start walking through each other, again resulting in one getting pushed up in the air... I'm close to dispairing...
I can't find that script for the life of me, when I find it I'll post it.
Your answer
Follow this Question
Related Questions
Rigidbody being affected by wind resistance - and wind! 0 Answers
Player bouncing off issue 1 Answer
Trees are flying when rigidbody is activated 1 Answer
Rocket-styled angular drag 0 Answers
Fly Mode 2D + Rigid Body vs CharacterController problems 0 Answers