Recently I upgraded a project from unity 5.0.0 to Unity 5.0.1 and discovered some quite erratic behaviour in the game. Note that the game has been in development for many months without issues across versions of unity from 4.3 onwards.
Update:
As a great example of how Unity are rapidly fixing bugs they replied within 2 days of me filling the bug confirming that they had reproduced it and had a fix. This was publicly available within 2 weeks as patch 5.0.1p3. Thankyou!
It shows that it’s worth while everyone taking the time to create a reproducible report of issues they discover.
Summary:
In Unity 5.0.0 patch 3 onwards including 5.0.1
(Tested up to latest release Unity 5.0.1 patch 1):
- If you set the RigidBody2D.CenterOfMass the inertia value will be calculated incorrectly which can cause erratic behaviour.
- Any prefabs (and possibly scenes) containing joints which had the collideConnected flag set will no longer have it set (and it’s now renamed to enableCollision) which will mean some objects no longer collide.
I have reported these issues as bug 691289.
Issue 1: Erratic behaviour after a collision.
When our character crashes their bike’s front suspension would go crazy, often sending the bike flying but eventually settling down with overly compressed with the wheel going through the bike’s body.
Many things are changed on a crash, but one by one they were ruled out until one was remaining. We have a child gameobject on the bike body which contains a box collider which is used for colliding with coin triggers and picking them up. It’s on it’s own layer and only interacts with the coins. When the user crashes this is switched off (as the player is ejected and we only want the player to collect coins after that)
So I created a testbed to investigate further and rolled back the versions of unity one patch at a time until I discovered that the behaviour was introduced in 5.0.0 patch 3
Bike 1 shows something close to what we have in game. Note that the red dot is the centre of mass (CoM) which we set via script.
Bike 2 shows how the bike settles after a crash. The bike is identical it just has the child BoxCollider2D disabled. I spent some time trying to identify a change in the wheel collider’s suspension, but none existed.
Bikes 3 & 4 mirror 1 & 2 with the exception being that we no longer set the CoM.
Bike 5 is just the bike body with he CoM set, notice that the inertia value is negative and the bike even intersects the floor as it erratically moves about.
Bike 6 is the same as Bike 5 but we no longer set the CoM
Running the same scene in Unity 5.0.0 patch 2 and previous versions results in the behaviour we would expect:
Reading the release notes and I suspect that the changes to implement the following have caused this issue:
Physics 2D: Center-of-mass and Inertia can now be set on a Rigidbody2D component even if it has no Collider2D components attached.
Once I had identified that the inertia values were wrong I was able to implement the following temporary fix which resets the inertia after editing the CoM:
float defaultInertia = body.inertia;
body.centerOfMass = transform.localPosition;
body.inertia = defaultInertia;
Should a child object effect the centre of mass?
Notice that between bike 3 and 4 the centre of mass moves down, this is not what I thought would happen. I believed that the only items to effect the rigid body would be those on the same gameobject as the rigid body it’s self.
This does pose the question of is this the intended behaviour and if so what is the best way to add additional colliders that move with the physics but do not alter the behaviour?
Please tweet any ideas to @hersee
You can download the unity project used to test this here: Physics2DIssue Use the scene window rather than the game window to see the collider outlines.
Issue 2: Our biker’s body started to travel through the bike.
This took longer to identify than it should due to a red herring. The following release note put us on the right track:
Physics 2D: Joint2D property ‘collideConnected’ renamed to ‘enableCollision’ to match 3D physics.
However I started at the wrong place, the hands which are connected to the handlebars. What was interesting was that disabling this joint caused the body to start to collide again. It wasn’t until a day later that I discovered the game code used the hinge enabled flag to control wether another joint should be active.
This other joint was indeed the issue as it connected the body to the bike, giving it a maximum distance it could travel. Anyway to cut a long story short if you have prefabs with joints that had the collideConnected flag set to true originally they will now have the new enableCollision flag but it will be set to false. Hence the connected object will no longer collide with what it is connected to.
At least that was a simple fix once discovered! Although I’m not sure why Unity’s FormerlySerializedAs attribute did not take care of this. Perhaps it’s not being used or there is a use case with prefabs where it does not work. I’ve done enough tracking down Unity’s issues today to bother checking this, also I don’t know if the same thing occurs with joints in scenes or if it’s just prefabs.