FINAL PROJECT

The game

You will try to reproduce a game from the Steam store called Coin Pusher Casino :

../_images/coin.png

Gameplay

Coin Pusher Casino is a virtual arcade game where you drop coins onto a moving platform, aiming to push others over the edge and into the tray at the bottom. Coins that fall in the tray are automatically collected and added to your total.

  • Player drop coins, one at a time, by clicking on the back wall

  • The click location determines where the coin is dropped from

  • Platforms are already filled with coins

  • Some platforms slowly slides back and forth

  • When your coin lands, it might:

    • Push other coins closer

    • Trigger a chain reaction

    • Knock coins or special prizes into the tray below

  • Coins that drop into the tray count as your winnings

In the game interface, the bottom tray isn’t really visible. So consider that any coin that falls all the way down is automatically collected.

Basic assets

Project setup

  • Create a new folder called Project

  • Insite this folder, create a new scene called POC and open it

  • Create a subfolder named Tokens in the Project folder

At the beginning, we will only use two elements:

  • The coins, which represents the falling coins and the small coins already on the platform

  • The casino chips, which are larger, colored and often stacked in columns

Chips look like classic casino chips, with values like $5 or $10 written on them. When they fall into the tray, their value is added to the player’s total. Coins, on the other hand, are just for pushing — they don’t award any money.

  • Download the following asset:

  • Drag and drop these files into the Tokens folder

Coins

  • Create a new material for the coin

    • Select a warm copper color

    • Increase its metallic property to give a metallic aspect

  • Create the Coin object

    • Drag and drop the obj file into the scene

    • Drag and drop the material into the object

    • Add a rigibody component

      • Set mass (10g)

      • Activate gravity

    • Add a mesh collider

Avertissement

Sometimes the mesh collider fails to detect the inner mesh and remains « empty »

../_images/empty1.png
  • In the Tokens folder, click on the coin asset to view its internal elements:

../_images/mesh.png
  • Drag and drop the default mesh into the missing mesh of the mesh collider

  • Enable the Convex option

  • Create the prefab

    • Drag and drop the object into the Tokens folder

Chips

Same procedure, except for the material where you have to assign the downloaded texture.

  • Set mass to 20g

../_images/folder.png ../_images/tokens.png

Pusher

The pusher has a specific behavior:

  • It follows a predefined path

  • It can push coins

  • Its movement is not affected by objects it collides with

By default, a Rigidbody reacts to forces and other objects in the scene. Fortunately, Unity provides an option called Kinematic which allows an object to behave like a pusher:

  • Ignores physics forces – The object won’t be affected by gravity or collisions

  • Doesn’t move automatically – It won’t react to physics; you must move it via a script

  • Still detects collisions – It can trigger collision events, but won’t be pushed or bounce

Here are the dimensions of the pusher:

../_images/pusher.png

Scene setup

  • Create a floor using a cube scaled to 5×1×20

    • Apply a solid color to this floor

  • Create the pusher using a cube scaled 5x0.6x20

    • Apply a solid color to this floor

    • Move the pusher so that it rests on the floor (compute the Y value precisely)

    • Move the pusher back

    • Add a Rigidbody

      • Enable its Kinematic flag

    ../_images/floorpusher.png
  • Build two walls on the left and right to prevent tokens from falling off the sides:

Animate

  • Create a script and attach it to the pusher

  • Look at the movement of the pusher, its speed is not constant

    • The pusher’s speed decreases at the extremities of its movement

    • Thus, we propose to animate the pusher using this formula:

\[z(t) = z_0 + K.sin(\omega.t) ~~~~ // ~~x(t) ~~also ~~possible\]

Thus:

  • As the pusher moves back and forth over a distance of 1, we know that \(K = 1\)

  • The period lasts 5 seconds, so you can deduce the value of \(\omega\)

  • The last step is to determine \(z_0\) from the environment you’ve built

../_images/sin.gif

Avertissement

If we simply change the position of the pusher, objects placed on it won’t move! To avoid this strange behavior, we need to move its Rigidbody instead of manipulating its Transform directly.

Vector3 pos = transform.position;
pos.z = ...
rb.MovePosition(pos);  // command the rigidbody

Proof of concept

Before spending hours on production, we’ll quickly set up a POC. If it’s too complex for Unity’s physics engine, there’s no point in going further. Everything is ready — create multiple coins and chips flying through the air. This way, they’ll fall like a waterfall, and we’ll be able to see if that works correctly!

../_images/test1.png

Here is our result:

../_images/firsttry.gif

For a first attempt, it’s really not bad at all!

  • The coins and chips fall as expected

  • They bounce realistically off the floor

  • The pusher moves the tokens forward

But there are still a few annoying issues:

  • Some tokens keep shaking and sliding around

  • Some tokens partially sink into the floor

Let’s be honest: you can tweak Rigidbody settings all you want, but it won’t fix the real issue. We’re overloading the physics engine with too many coins, all in constant contact. This is pretty much a nightmare scenario for physics, way more complex than simulating a car driving on a road.

But the 3D engine almost manages to handle it — it just seems to lack precision. As a reminder, physics is simulated by discretizing time into fixed steps, which are set to 0.02 second by default. That timestep is still too large for our fast-falling, bouncing coins. Let’s reduce it by a factor of 10 and see how the engine reacts:

  • Navigate to: Menu > Edit > Project Settings > Time

../_images/time.png
  • Set Timestep to 0.002

  • Enter Play mode

../_images/gogo.gif

Wow, great, it works like a charm!