p2.js
p2.js copied to clipboard
Wiki page idea: high-level optimization advice
It'd be a great asset to the community if there was a high-level bulleted-list / check-list of sorts that enumerates the various optimizations to consider, ideally with some sample implementation, from simple to advanced.
I reckon a lot of people are like me, kind faking it til they make it with their physics simulation, and could use some preliminary guidance and examples to get into the headspace of optimizing a physics simulation and where to find the low-hanging fruit.
For example, in which cases would one use shape.sensor = true
vs shape.collisionResponse = false
, and what's the actual impact of them?
I'm definitely not in a position to write such a list, but here are some examples that might not be accurate -- just for demonstration:
-
Reduce the amount of shapes and bodies when you can.
Example: Instead of creating a fixed-sizep2.Box
for each collidable wall-tile in your map, replace lines of adjacent tiles with a singlep2.Box
that spans all of those tiles. -
Use collision groups and masks to avoid extraneous collision calculations. Example: If your game has a red team and a blue team, and players on the same team cannot shoot each other (no friendly-fire), then the simulation would be doing extra work by checking for collisions between red team's bombs and red team's players. Instead, you can use groups/masks like this: [flesh out with better code example]:
redPlayer.collisionGroup = RED_PLAYER redPlayer.collisionGroup = WALL | BLUE_BOMB redBomb.collisionGroup = RED_BOMB redBomb.collisionMask = WALL | BLUE_PLAYER
-
[Explain broadphase vs narrowphase and how/why you'd want to filter out bodies in the broadphase]. Outdated, but a good example of an easy to understand explanation: http://paulsalaets.com/posts/selecting-broadphase-p2
-
How to profile your p2 simulation.
Good idea! I think the list could become pretty long and contain many game-genre specific things...
Some things I'd like to add to the list:
-
Use larger timesteps (fixedDeltaTime).
For example, runningworld.step(fixedDeltaTime, deltaTime, maxSubSteps)
withfixedDeltaTime=0.2
instead of0.1
will improve performance with 2x! On the other hand, it can make your collisions spongy and allow more penetration. If so, try reducing velocity of your objects, or reducing gravity a bit. -
Reduce the number of solver iterations
world.solver.iterations = 3; // Fast, but contacts might look squishy... world.solver.iterations = 10; // Slow, but contacts look better!
-
Use simplified collision shapes.
The simplest collision shapes are best for performance. If you can use ap2.Circle
instead of ap2.Convex
for your player shape, then you should. -
Turn off friction.
If you don't need friction for an object, then turn it off. Just setmyContactMaterial.friction=0
. This will reduce the load on the solver. -
Enable sleeping
If an object is not moving, it can be automatically deactivated by using the following code.body.allowSleep = true; body.sleepSpeedLimit = 1; // Body will feel sleepy if speed < 1 body.sleepTimeLimit = 1; // Body falls asleep after being sleepy for 1s world.sleepMode = p2.World.BODY_SLEEPING;
If you need to make sure a body is activated, just run
body.wakeUp();
. -
Remove bodies from the world when they don't need to be simulated. Example: if you're making a large game world, or a game with multiple rooms, you can easily remove physics objects that the player doesn't see on the screen.
var distanceToPlayer = p2.vec2.distance(playerBody.position, enemyBody.position); var isAddedToWorld = enemyBody.world !== null; if(distanceToPlayer < 20 && !isAddedToWorld){ // Enemy is close to the player. world.addBody(enemyBody); } else if(distanceToPlayer > 20 && isAddedToWorld){ // Enemy is far away from the player. world.removeBody(enemyBody); }
What do you think?
Any ideas for the format of the "How to profile" part?