SpriteKit - Why my bouncing ball passes through the ground? - ios

I'm working for a small bouncing ball game using the SpriteKit physics engine. My problem is:
When I apply a huge impulse on the bouncing ball to have it fall on ground fast, sometimes it may pass through the ground (very thin, height=2).
I find this in the Apple document, but it doesn't work.
Specify High Precision Collisions for Small or Fast-Moving Objects
When Sprite Kit performs collision detection, it first determines the locations of all of the physics bodies in the scene. Then it determines whether collisions or contacts occurred. This computational method is fast, but can sometimes result in missed collisions. A small body might move so fast that it completely passes through another physics body without ever having a frame of animation where the two touch each other.
If you have physics bodies that must collide, you can hint to Sprite Kit to use a more precise collision model to check for interactions. This model is more expensive, so it should be used sparingly. When either body uses precise collisions, multiple movement positions are contacted and tested to ensure that all contacts are detected.
ship.physicsBody.usesPreciseCollisionDetection = YES;

You can set your sprite's node.physicsBody.usesPreciseCollisionDetection = YES; but this will not guarantee a collision flag all the time as your sprite's velocity could simply be just too high.
You should apply a speed limit to your nodes as to prevent them from going too fast. Something like this:
if(node.physicsBody.velocity.dx > 200)
node.physicsBody.velocity = CGVectorMake(200, node.physicsBody.velocity.dy);
The above code example will limit the right movement, dx, of your node to 200 while keeping the dy (up/down) velocity as is.

Related

Spritekit - applying an acceleration to a physics body

I'm working on a project where I have a node affected by gravity. I would like to be able to apply a vertical acceleration to this node without touching gravity. Pretty much like a hot air balloon that I would make go up or down while other objects are still normally affected by gravity.
balloon = Vehicle()
balloon.physicsBody = SKPhysicsBody(polygonFrom: path)
balloon.physicsBody?.affectedByGravity = true
I tried playing around with applyForce(_:) and impulse but what I'd like is a proper acceleration and not a punctual impulse to defy gravity over time! Any suggestion?
What you're looking for are physics fields (SKFieldNode), in Sprite Kit.
These provide the ability to influence objects with general forces, like wind, lift, black hole style attraction etc.
You can read about them here.
The really important consideration of how they can work is in this quote:
Physics bodies with affectedByGravity set to false are still affected
by the gravity fields created by linearGravityField(withVector:) and
radialGravityField().
But what they forgot to also make clear(er) is that objects influenced by gravity are ALSO influenced by these fields.

SceneKit collision occasionally fails

I'm trying to simulate a soccer game. I have a SCNPlane that simulates the court. I have imported a Soccer goal 3d model (.dae file) and also a ball model (.dae).
My ball has a dynamic physics body, the plane static and the goal is kinematic. I have set the categoryBitMask and contactTestBitMask for each one of the SCNNodes.
When I shoot the ball against the goal then sometimes the ball bounces and behaves as expected, but some other times the ball goes through the goal net and crosses it.
I have also assigned the SCNPhysicsContactDelegate and the didBeginContact is triggered when the ball bounces agains the goal but when the ball crosses it then the method is not called.
Do you know what might be happening?
Thank you!
Might be an issue with the ball moving too fast for the physics engine to calculate correctly. Try changing the "timeStep" value:
SceneKit processes the physics simulation and updates the state of all
physics bodies once per the time interval specified by this property.
The default value is 1/60 second (a rate of 60 Hz). A faster
simulation rate provides more accuracy in simulation results—such as
collisions between fast-moving objects—but at a higher cost in CPU
time (which may in turn slow down your app’s rendering frame rate).
Typically, you should set this property to match your target rendering
frame rate (as defined by the preferredFramesPerSecond property of the
SCNView object rendering your scene).
https://developer.apple.com/documentation/scenekit/scnphysicsworld/1512881-timestep
Instance property categoryBitMask defines which categories a physics body belongs to, and contactTestBitMask defines which categories of bodies cause intersection notifications with this physics body.
You need a collisionBitMask instance property that defines which categories of physics bodies can collide with this physics body.
var collisionBitMask: Int { get set }
When two physics bodies contact each other, a collision may occur. SceneKit compares the body’s collision mask to the other body’s category mask by performing a bitwise AND operation. If the result is a nonzero value, then the body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body. For example, you might choose to avoid collision calculations that would make negligible changes to a body’s velocity.
The default value is all (a bit mask whose every bit is enabled), specifying that the body will collide with bodies of all other categories.
static var all: SCNPhysicsCollisionCategory { get }
all is default Type Property for a physics body’s collisionBitMask property.

How to get Constant Velocity for Spritekit Gravity

I am making a Tetris kind of game, where I want my blocks to fall at a constant velocity. I want to achieve it using SpriteKit Physics Words Gravity.
Problem is that gravity is necessarily acceleration and hence block start to move faster as they fall. I know I can turn gravity off and use actions to move the block but I wish to do it with gravity.
Is there a way to make the gravitational force in SpriteKit world a linear constant velocity?
Using the default physics you will not achieve what you are looking for.
In the definition of Gravity in Spite Kit is clear that is a acceleration, so is no possible to achieve linear speed with it.
A vector that specifies the gravitational acceleration applied to
physics bodies in the physics world.
But, you can have some workarounds to achieve the behavior you want.
Gravity Acceleration 0, and add speed to the falling object.
Limit the maximum Speed of an Object.
Do you own physics
I Think the best way to do it, with gravity working as default, is by limiting the maximum speed.
2 - Limit the maximum Speed
Consulting this post.
In didSimulatePhysics(), you can verify the speed of the object, and limit it.
Like this (Credits to #Andrew, in the original post)
- (void)didSimulatePhysics {
if (node.physicsBody.velocity.x < MAX_SPEED_X) {
node.physicsBody.velocity = CGVectorMake(MAX_SPEED_X, MAX_SPEED_Y);
}
}

SKSpriteKit how to control Impulse or Force speed?

Hi guys i want to apply slow motion in upward direction,
what i am confused, when i applyimpulse
[self.physicsBody applyImpulse:CGVectorMake(0, 60)];
it does applyimpulse with required speed as it measure from its velocity mass and other physics things
what i need to applyImpulse but with controlling speed of impluse that is applied on object on which impulse is being applied.
i tried to set even self.speed but got no success,
how one can achieve desired impluse or Force on an sprite with controlling over speed.
are there some properties that should i set for the SKSpriteNode before applying Impulse,
or some thing else?
Any suggestion or thoughts will be appreciated
Thanks
The speed property of SKNode is to do with SKActions, however the speed property of SKPhysicsWorld is what you probably want to tweak to achieve physics in slow motion.
It says the following in the documentation about the speed property of SKPhysicsWorld
The default value is 1.0, which means the simulation runs at normal speed. A value other than the default changes the rate at which time passes in the physics simulation. For example, a speed value of 2.0 indicates that time in the physics simulation passes twice as fast as the scene’s simulation time. A value of 0.0 pauses the physics simulation.
Access it from within your SKScene subclass like this-
self.physicsWorld.speed = 0.5; // half speed (slow motion)
All forces are applied as actual physics forces on physics bodies.
The resulting movement of the body that had the force applied to it depends on not just the magnitude and direction of the force but also the size and density (i.e. mass) of the body the force is being applied to and where on the body the force is applied.
I'm not entirely sure what you mean when you say you need "controlling speed of impulse" though.
Maybe what you need is not to use forces at all but to move the node manually.
You could use an action [SKAction moveByX:y:] or update the position in the update method. This way you can control the speed of the movement exactly.

Physics Material slow down the game

I have developed game something like coin dozer. And for the smooth movement of coin i have add one Physics Material to each coin but my game is very slow after doing that . Is there any alternative of that or how can i make coin movement smooth without use of Physics material . So can anybody help me to come out from this situation.
So the problem is physics calculation.
DO NOT use the mesh of the graphic as the collider to calculate coin's moving, especially when there are lots of triangles and verts on the mesh. You should choose a simpler collider, maybe something like prism would behavior similar as a coin and reduce a lot of calculation. You can use another simple prism mesh exported from 3d software and make a new game object with that mesh. Stripe off everything related to physics(rigid body, collider and physics material) from the origin coin. Then organize the visible coin without physics and the new added object(which handle all physics) to the same parent. Less triangles in a mesh collider means less calculation. Control the collider mesh triangles as few as possible. I suggest to use a box collider as a start point to check if the performance improves.
Another thing might help is changing the Solver Iteration Count in the Physics Setting. You can try to change it to a lower value (maybe 3 or 4 is enough for a coin game) from the default.
Limit the frame rate to a lower value alse can help, but it is the last way you should go.
You can add physics to the coins with delay. I mean add physics when coin is near to fall. Also you need to destroy every coin body when you are removing the coin out of the scene. If you are removing only sprite the there will be too many bodies on the scene.

Resources