Fast Physics 2D on mobile platforms

I’m trying to replicate classical Bricks and Ball games like this one: https://play.google.com/store/apps/details?id=com.peoplefun.bricksnballs&hl=en_US&gl=US

I’m trying to approach a design based on Physics2D, but I’m facing the following problems:
-Mobile devices are usually constrained to 30fps
-Fast objects are hard to manage with physics

So I’ve been doing my research and apply the classic stuff:
-Try to raycast for avoiding fast objects cross walls (edge colliders)
-Fixing my Fixed Timestep to the according fps (0.03)
-Removing any logic on the moving object from the Update to FixedUpdate
-Interpolate movement to have a smooth effect

Stuff like that, but even like this I can not achieve the accuracy of the game linked, cause balls bounces looks like teleportations, cross lot of walls etc, this is how my game looks like:
https://im3.ezgif.com/tmp/ezgif-3-714cda173a.gif
(the gif runs at 33 fps to be similiar of how it looks on editor)

The game is composed by:
-A bunch of edge colliders that act as external walls
-Every brick has a box collider
-Ball has a circle collider with a rigidbody2d with collision detection on Continous and Interpolate and a 2D Physics Material with 0 friction and 1 bounciness.
-The ball is instantiated and added a velocity (with initialSpeed = 40) with the following code:

//Add Ball velocity and direction
var direction = toPosition - ballGO.transform.position;
ballGO.GetComponent<Rigidbody2D>().velocity = new Vector2(direction.x, direction.y).normalized * initialBallSpeed;

Summarizing:
-Do you think those developers are approaching a “physics based system” for this kind of games?
-If Yes, what do you recommend me to look at to fix my gameplay?

Edit: @MelvMay

This shouldn’t be the case, this is what continuous collision detection is for. To stop tunnelling in fast-moving objects or lower frequency simulation steps.

It’s not clear what approach you’re using in the image and if it’s raycasting or continuous collision detection.

Continuous in 2D physics is rock solid so you won’t be getting tunnelling even if the simulation is running at 1Hz so something else has to be going on here. If you’re raycasting, you might find you’re starting your ray just beyond the edge because they’re essentially infinitely thin. You can backoff the raycasts by a small margin or just add a small EdgeRadius value to the edges.

It depends on your game but you are free to run the physics per-frame if you wish. Just change it in the Project Settings > Physics 2D > Simulation Mode. You no longer need to use FixedUpdate as it runs per-frame and interpolation is ignored automatically. The downside here is that very low frame-rates means low simulation rates but for a lot of games it doesn’t matter.

Maybe just use this to isolate what’s going on.

Although not a cause of tunnelling, you should set the following property which controls at what point a collision is counted as inelastic (no bounce): https://docs.unity3d.com/ScriptReference/Physics2D-velocityThreshold.html. That said, your velocities look very high so unlikely you’ll see this but lower velocities will hit it.

Just a small observation but don’t use the Transform as a reference to position, it’s not the authority, the Rigidbody2D is. This is especially true when using interpolation because the Transform is historic i.e. it’s moving from the previous body position to the current one. Use Rigidbody2D.position always.

I will say that it’s not clear what the code above is doing. It’s more typical to re-normalise the velocity itself to a set speed. I don’t follow what “toPosition” is.

The gif attached is showing the game with only continuous collision detection working, so any problem with Raycast should not apply to the recording.

I’ve tried right now, it makes no difference changin simulation mode from Fixed Update to Update or Script.

I do not know about that, I will keep it in mind, but as you state, yes, velocities are very high :frowning: in fact I think that the whole problem is this, that object is too much fast, but if you say that this should not be a problem with Physics2D…

Got it, the problem is that I’m not really performing anything on the transform itself right now, but I’ll keep it in mind if I do something with it later.

I’ve tried to simplify on a single class all the code in case if serves as a hint on how it works the code and what the “toPosition” do:

public class GameViewManager : MonoBehaviour
{
    public GameObject ball_prefab; //prefab of the ball GO
    public GameObject launcher; //Square gameObject that looks like a "canon"
    public Transform ballsParent; //Empty gameObject to stablish where on the hierarchy to spawn the balls

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            ShootFromTo(
                launcher.transform.position,
                Camera.main.ScreenToWorldPoint(Input.mousePosition),
                ballsParent);
        }
    }

    public void ShootFromTo(Vector3 fromPosition, Vector3 toPosition, Transform parent)
    {
        //Instantiate Ball
        GameObject go = GameObject.Instantiate(ball_prefab);
        go.transform.SetParent(parent, false);
        go.transform.position = fromPosition;

        //Add Ball velocity and direction
        var direction = toPosition - go.transform.position;
        go.GetComponent<Rigidbody2D>().velocity = new Vector2(direction.x, direction.y).normalized * initialBallSpeed;
    }
}

Edit: My main concern maybe it’s not well defined, my problem is not so focused on how to avoid tunneling, is on how to achieve the feeling (that other games have) of smoothness with fast physics objects, even on mobile devices that are constrained to 30fps.

1 Like

I’m very curious about the tunnelling. If you can reproduce this in a simple, focused test project I’d love to take a look. Either host it here or ping me privately with your email and I’ll set-up a private place for you to upload.

Interpolation obviously means it’ll move at 30fps which is as smooth as it gets at that rate; there isn’t any smoother so nothing to really suggest beyond that apart from making physics run per-frame so you don’t have to also adjust the FixedUpdate rate which you could also set to be 30Hz rather than the default of 50Hz. I presume you’re also using Application.targetFrameRate = 30? You can use that as a test too away from mobile.

Smoothness is one of those things which needs to be seen. If you simply manipulate a Sprite (say) via Transform back//forward, is that any “smoother”? If so then something is going wrong with the interpolation but that’s hard to see why because it’s such a simple thing.

Sorry, I’m not sure I’m helping but it’s very hard to know what to suggest without seeing the issue.

Also a minor thing but the following code…

GameObject go = GameObject.Instantiate(ball_prefab);
go.transform.SetParent(parent, false);
go.transform.position = fromPosition;

… should be …

GameObject go = Instantiate(ball_prefab, parent, fromPosition, Quaternion.Identity);
...because otherwise the "go" is created at (0,0,0) and so is the Rigidbody2D component. Subsequently changing the Transform is something you shouldn't do because it'll not happen until the next simulation step. Can be minor but also a source of subtle bugs.
1 Like

Sorry for the delay on the response @MelvMay but I spent some time trying to achieve a different conclusion of the initial one, but without too much success.

The cruel reality is this one:

Even without interpolation, the problem remains the same, if you are moving something in 30fps faster than that 30 fps admit, it will look like the item is teleporting itself.

After downloading multiple similar games, I’ve come to the conclusion that these games simply move the ball slowly, but when spawning several at the same time, and being on a smaller screen such as a mobile, it seems faster than it really is.
I have timed (on those games) how long it took for a ball to hit a side wall opposite to the impact site and indeed, the speed was practically 3 times less than what I was trying to replicate.

So it seems that the logic conclusion is:
“You want a game with a fast moving object that looks smooth? Target a higher frame rate!”

I can if you want, but after trying it, the tunneling problem only appears with objects that (due to bounce factors higher than 1) have an exponentially increased velocity, and they reach ridiculous speeds like 30000 on a single axis. So for a normal gameplay as you state, rigidbodies are rock solid ^^’

Don’t worry, was my bad, I was illogically expecting to be able to move an object smoothly regardless of frame rate, and it makes no sense v.v

Thanks again for your time!

Ultimately yes, you cannot get smoother than the display update that the device can achieve along with how good the LCD display rise/fall times are. The faster the better, hence those nice 120Hz displays are some mobiles. :slight_smile:

Right, so 30 km/s or Mach 88160 is a tad fast!! You’re potentially hitting not limits on intersection but the impulse forces for bouncing/solving would be HUGE leading to serious problems such as overshoot.

Never a problem.

1 Like