- Home /
Side scroller and physics
I have been creating a side scroller game with boxes. The player is a box that needs to walk over platforms trying to avoid getting hit or falling. The source code is hosted in github.
The game has:
A `Player`. The player looks like this:
It has:
A box collider to walk over platforms
A capsule collider to detect when it hit something on it's front (it should die)
A box collider below the platform to detect when it falls into a hole (it should die)
The platforms are just box colliders.
Physics:
Gravity: x=0; y=-60; z=0
Bounce Threshold: 0
Sleep Velocity: 0
Sleep Angular Velocity: 0
Max Angular Velocity: 0
Min Penetration For..: 0.01
Solver Iteration Count: 2
Raycasts Iteration Count: 2
Raycasts Hit Trigger: On
If you run the code you will notice that sometimes the player just dies. It usually happens where two platforms are together. I noticed that lowering the `Fixed Step` in the `TimeManager` fixes the issue but it makes the game look slow in some devices.
What would you recommend to fix this issue?
Update: I just modified the code to do: `Time.timeScale = 0.0f;` when the player dies. This usually happens after a jump. Check the screenshot, there is no intersection where it fails :(
Update 2:
I just updated the code. I added logic to check if the trigger was done against a border. The code is the following:
MeshFilter mf = other.gameObject.GetComponent<MeshFilter>();
Vector3 objSize = mf.sharedMesh.bounds.size;
Vector3 objScale = other.gameObject.transform.lossyScale;
float objWidth = objSize.x * objScale.x;
float leftBorder = other.gameObject.transform.position.x - objWidth * .5f;
float diff = Mathf.Abs(this.transform.position.x - leftBorder);
if ( diff < 0.3f )
{
NotifyDeath ();
}
Now you don't die randomly, but sometimes you end up going through platforms as you can see in the following screenshot:
My guess is that the issue is the `gravity.y = -60`. The player hits the floor with a lot of speed and the Fixed Timestep is too long.
I will now start playing with `gravity.y = -9.81` and modifying the jump force magnitude to see if it improves.
Update 3:
I tested what @loopyllama mentioned. I just pushed the code with the capsule collider inside a second `gameObject`. The problem with this approach is that the capsule collider doesn't follow the body.
The second thing I tried is making the FrontBumper a child of the body. This makes the capsule collider follow the body, BUT when there is a collision, `OnCollisionEnter()` is not called in the DeathByPlatform script, it is called in the Player script. I tried modifying the capsule collider to make it trigger and now the `OnTriggerEnter()` is called inside the DeathByPlatform script. This works but the behavior is the same, sometimes you die when you hit a platform from the top :(
Answer by loopyllama · Nov 28, 2012 at 07:30 PM
download the fixed project here
did you remember to mark the capsule collider as kinematic and to ignore the other box collider that is a part of the player?
not related to your question, if I were you I would completely avoid physics (unless it was somehow key to your game design) and instead limit the interactions to simple triggers.
Ok, here is your solution. Make a new script:
public class DeathByPlatform : MonoBehaviour
{
public Player playerScript;
void OnCollisionEnter()
{
if(playerScript != null)
playerScript.NotifyDeath();
}
}
duplicate the body and rename is something like FrontBumper. Delete eerything but the rigidbody and capsule collider. Attach this new script to it. drag the instance of the player script in the newly added component (I think you have it on the Body). Make the NotifyDeath in Player.cs public. Remove the capsule collider from the body. In players.cs comment out the notifydeath in oncollisionenter. It will work now.
What was happening? You have two colliders on the body: Box and Capsule. The box is what you use for running across a floor and the capsule is your fron bumper that should trigger a death. Your demo would have the box touch the floor and you can detect that the floor was struck, but it is not clear if it was the box (safe) or capsule (death). The solution is to have a different game object that is resposible for the dying (capsule) and attaching above script.
I can't put the capsule colloder as `kinematic` since it uses the same `gameObject` as the box collider.
"kinematic" means "hey unity, I am going to move this around so you had better update the position of the collision" and it is a property of the collider component, not of a game object. For that matter, you should also set the box collider to kinematic as well...
@loppyllama: I have tried turning it on, but if I do it doesn't move in the y axis. The gravity doesn't affect it.
ah right, so...you can leave is$$anonymous$$inematic unchecked and try setting Collision Detection to discrete on the Rigidbody. you might want to post the intersection of platforms that exhibits the issue. I still stand by my suggestion of rolling your own gravity and only use physics for triggers...
@loopyllama: I just pushed the updated code and I updated the question with a screenshot where it fails.