The 2D gameplay mechanics pack is a full-fledged tool that contains a broad set of 2D gameplay mechanics (player’s specific mechanics). Fast and easy setup for almost any type of 2D platformer game.
With over twenty mechanics (See the full list down below), that is pretty much all you need to make an awesome 2D platformer game.
All the code is optimized for cross-platform development, and the pack has been tested on PC, Android, and on the Web. Note that for IOS devices it has not been tested.
I have prepared prefabs for everything (i.e., Players, objects, etc.) so it’s advisable to follow their structure. Moreover, down below there is a step-by-step guide to set up the controller from scratch.
A flexible and high-performance pool system is used for all mechanics that need to spawn and destroy game objects. So, when you choose a mechanic that requires spawning a game object, a pool script will be added to the player game object to manages it. However, you do not need to worry about this script. Because in each mechanic tab, when a prefab is required all the pool configuration will be displayed underneath it, so you will be able to configure them from the mechanic tab.
The controller supports four different types of collisions:
1) Box collider.
2) Box collider along with edge collider. Use this with dash abilities. Or if you found any issues with normal box collider, otherwise stick to Box Collider.
3) Capsule collider along with edge collider. The best collision setup for all human like character, specially animated ones. Edge collider added automatically to handle collision properly, so player won’t get stuck to ground due to the capsule shape.
4) Circle collider.
Tip: For all 2D platformer games that I have worked on, I could tell that the best collision setup requires an additional edge collider whether it was Box or Capsule collider.
How To Install
1) Create a new project from the Unity Hub.
2) Import the pack from the Asset store to the new empty project (IMPORTANT! It has to be an empty project because the pack comes with project settings already configured and they will overwrite yours if you imported the pack to an existing project).
3) After you have imported the package successfully, you will see an errors in the console. And that's because the pack uses package manager dependences. And I deliberately decided not to include any dependences which in some cases might wreck your project. Instead Open the package manager and download the new input system package.
4) Restart the editor. This is important because the new input package doesn't take effect unless you restart the editor.
See Input System section for further details.
Setup Controller (Step-by-step guide)
There are nine different types of players already prepared for you. So, I advise you to see how they were configured.
Step by step guide:
1) Create an empty Game object in the scene and rename it whatever you like (i.e., Player)
which will represent the object that holds the controller.
2) Create a child Game object and add to it a sprite renderer component. Then add your character sprite to it.
3) Back to the parent object, in the inspector window click “Add Component” and add the “Gameplay Mechanics script” to it.
4) In the main tab you can choose your preferable collider(s) type and tweak them directly from the main menu, However I personally prefer that you only select your preferable collider(s) and later after the controller is set you can adjust them directly from their components using the Edit Collider tool.
5) If your character has animations and you want to set an animator controller, then make sure to tick the flag “Is player animated ?.”
6) Now press the Setup Controller button. If you make a mistake or for any reason the controller is not working properly you can press the Reset Controller button and set up the controller again. Important note: This button only resets the collision and rigid body components, so it does not reset any of the mechanic.
7) Once you have pressed (Setup Controller), the controller will have been set. Now you can add, remove, or customize any gameplay mechanic by navigating to (Gameplay Mechanics) tab.
Important Notes
1) Make sure your character is tagged as “Player”. Because in some cases I get a reference to the player based on his/her tag.
2) Make sure your character’s sprite is the first child to the parent Game object (Player). This is especially important if your character is animated, which allows the controller to add an “Animator controller” component to it.
3) Make sure ray casts are long enough and covering the whole character, the same thing goes to overlap sphere for better experience, which helps detect the ground in all cases. Ex: when half the player is on edge and the other in air.
4) Neither crouch nor slide is allowed when using a circle collider.
5) The controller uses rigid body physics.
6) IMPORTANT !
All the assets used in the showcase and in the demos are free assets, and all the rights for the asset owners.
Please refer to the "Demo Assets Credits" link at the top of the page in the table of contents. You will find a pdf file that contains the credits for all the assets used in the showcase and the demos.
I don't have the right to redistribute them, so they don't come with the pack. They are only used for showcasing the mechanics.
Input System
The pack uses the new input system, in the project files you will find a “Gameplay” action map already set for all types of input such as, Mouse & Keyboard, Gamepad, and Touch. You can easily modify and bind inputs to any mechanics from the action map.
Important: You have first to download the new input system from the package window, you can do so by going to “Window/Package Manager” then from the drop-down menu in the top, select “Packages: Unity Registry” and then search for Input System and simply hit Install.
Finally, in the project settings make sure that “ActiveInputHandling” is set to “Both”. You can find it in the project settings under the player tab.
Gameplay Mechanics
Ground Check
Two methods to check if a player is grounded or not. You can select the one that suits your player the best.
1) Physics2D.OverlapCircle() => You can modify the radius and offset of the circle.
2) Physics2D.Raycast() => Two rays from both legs to better jumping experience. You can offset them horizontally, so they cover all edges (Span from left to right).
The starting point (Origin) for both methods is a vector3 which you can alter its location in the editor.
Movement
Apply forces to move the player on the x-axis based on user input.
Forces are much smoother than just updating velocities when to comes to movement. However, they tend to make the player slides a little bit, so the system uses a state to determine when to move and when to stop so it can prevent sliding from happening through controlling the linear drag affecting the body.
In the case of a circular character (e.g., ball) where there is a need for rolling a torque is used to roll the ball. There is an option in the movement mechanics tab called (addTorque) just tick the flag when you have a circle collider and you want the ball to roll. I also provided an option to stop character flipping in case you would like to. You can do so through a flag called (disableCharacterFlipping).
In the movement tab you can adjust the player’s speed when grounded as well as in air, so the player would have variant movement. Additionally, there is a variable to change the player’s speed in air while sprinting.
The velocity will be clamped to a maximum speed, so player will not keep accelerating infinitely
(Note that both values movement speed & maxMovement speed could be the same).
As I mentioned before, forces tend to make the player slide a little bit, especially when there is a change in direction. (TacklePlayerSliding() & HandlePhysics()) methods handle this issue. When player leaves the horizontal input and the character starts slowing down this is being represented by the state (PlayerMovementState.PlanToStop), during this state we add a linear drag (obviously you can adjust the value that works best for your player), when the player stops completely this is being represented by the state (PlayerMovementState.Stop) we set the linear drag and gravity Scale to their initial values, so player can start moving smoothly.
Jump
Different types of jump mechanics described as follows:
1) Normal jump, where the player can only jump a constant amount.
2) Hold to jump higher, in addition to the normal jump, player can also hold the jump button to jump even higher that is accomplished by controlling the gravity scale property of the rigid body.
3) Double jump or more, you can make the player jump as many times as you want by updating the field (jumpCounter). 1 => means double jump, 2 => means triple jump, and so on and so forth.
After determining the type, the jump() function adds force to thrust the player upwards.
Besides the jump type, you can also choose to have a coyote time, which gives the player a grace period after leaving the ground. Thus, the player can still jump after leaving the ground for a small amount of time represented in seconds through (Coyote timer) variable in the jump tab.
Note: If for any reason you decided not to use the coytoe feature. Make sure that you set the (CoyoteTimer) to a value greater than zero, otherwise the jump won’t happen. A small value like 0.001 would do.
Another feature you can add is jump buffering, which allows the player to press the jump button in the air and then once hitting the ground the player will jump again. This is achieved through the flag (AllowJumpBuffering). Note that you cannot change the time for this feature to take place, it simply caches the jump button when pressed and when the player falls again on the ground it happens.
Sprint
Linearly interpolates between the current player's movement speed and the specified (sprintingSpeed) by the value indicated by the variable (sprintingSmoothingTime).
I have provided a variable in the sprint menu tab (RunAnimationSpeed), which you can use to change the animation speed, so it matches the sprinting speed.
Crouch
Note that crouching is not allowed for circle colliders.
1) For animated characters you can play the animation and adjust the colliders according to it. Instead of changing the colliders and modifying them manually which can be very tedious. I have provided an easy way to do that. There are two buttons (save original colliders values) and (save crouch colliders values) in the crouch menu tab. First press the button (save original colliders values) to save the original values so you don't need to change them back, then modify the colliders as you like from the inspector window, then press the button (save crouch colliders values) to save the crouch values, then the original values will be automatically set back to their original values.
2) For non-animated characters you do the same as the steps mentioned above. However, I have provided a simple setup up where you can squish & unsquash your character to simulate the effect of crouching.
For the crouch mechanics itself . I simply alter the whole movement of the body by slowing it down.
Physics2D.OverlapCircle() => To check objects above player's head while crouching. If any object detected, the player will be forced to stay in crouch state even if he/she releases the crouch input.
Slide
Note that sliding is not allowed for circle colliders.
1) For animated characters you can play the animation and adjust the colliders according to it. Instead of changing the colliders and modifying them manually which can be very tedious. I have provided an easy way to do that. There are two buttons (save original colliders values) and (save slide colliders values) in the slide menu tab. First press the button (save original colliders values) to save the original values so you don't need to change them back, then modify the colliders as you like from the inspector window, then press the button (save slide colliders values) to save the slide values, then the original values will be automatically set back to their original values.
2) For non-animated characters you do the same as the steps mentioned above. However, I have provided a simple setup up where you can squish & unsquash your character to simulate the effect of crouching.
For the mechanics itself I use forces to move the player in the direction of sliding as an impulse as well as modifying the linear drag and gravity scale of the body to make the sliding happen smoothly.
Physics2D.OverlapCircle() => To check objects above player's head while sliding. If any object detected, the player will be forced to stay in slide state even if he/she releases the slide input.
Push & Pull
Single ray to detect the object to be pushed or pulled (both mechanics built together that means the push happens when the player pushes forward, and the pull happens when the player pulls backward all while pressing the push & pull input). You can select a specific layer for the object. However, the system detects the object using tags, so you must tag the object. Finally, physics constraints will be used to handle this mechanic.
For this to work you must setup the object as follows:
1) Add a preferred collider.
2) Add rigid body component and adjust the mass appropriate to your object.
3) Add fixed joint component and disable it.
4) Add appropriate tag and different layer (optional). And that's it.
Important note: This mechanic doesn't use any new forces; it only affects the object by the forces applied to the player’s movement. But I provided you with the ability to change the movement speed while pushing or pulling. However, you shouldn’t use high speed, otherwise the joint will break.
See example object in prefabs/Misc.
Wall Mechanics
Wall slide
When the player approaches a wall while holding the horizontal input towards it the sliding mechanic will occur. If there wasn’t any horizontal input, then simply the player will be forced to ground using only gravity. Once the player starts decelerating, a sliding speed will be added to the body.
Wall pop
When the player approaches a wall while pressing the jump button without any other input a small push will affect the player backward.
By constructing a new vector right above the player Y position as the (in) vector towards the wall and then uses vector reflections to calculate the reflected vector, after that I simply use AddForce() method to push the player backward
Wall jump
When the player approaches a wall while pressing the jump button as well as the horizontal input being held, the player will jump from one direction to another. I provide a vector2 where you can specify the speed added in both axes.
Note: Jumping on the same wall direction not configured. That means the player will always jump in the opposite direction.
Wall climb
When the player approaches a wall while pressing the climb button, then he/she can use the vertical input to climb up or down. If the climb input was released, then the player will be forced to the ground.
Auto ledge
When the player reaches the edge of the wall, an auto ledge mechanic will take place (No animation applied. Instead I calculate the exact height and width needed to push the player on top of the wall using ray casts. Even though I calculate the exact height I still provide a variable called (maxWallLedgeHeightExtendedValue) where you could use to extend the height if you need the player to jump in the air a little bit instead of being transformed to the exact height.
Note: Auto ledge only happens when the player reaches the edge of the wall after climbing.
Fly & Jetpack
Free fly
In the case of animated characters, only an elevation animation is considered (So if your character doesn't have an elevation animation it’s not that important). The reason why I did not use a specific animation for flying is that I want the player to fly freely in all directions while keeping the player head always facing the right angle. If you want to use an animation for flying, you have to worry about adjusting the collision according to each angle the player rotates towards. Which is going to be cumbersome in this situation.
The fly key will be responsible for elevating the player off the ground for a certain period determined by the (elevationTime) variable. Then the player can use the horizontal & vertical input to move freely in space.
If the player stands still in mid-air, a wiggle mechanic would take place that uses sine waves to generate a wiggle effect (Simply moves the player up and down continuously). You can disable it if you want to save a little performance.
Jetpack
Two ways of jetpack mechanic. The typical one which you can use jetpack only in one
direction (only Right) and Both. You can use the variable (jetpackRotationMultiplier) to rotate the player a little bit while jetpacking. Additionally, you can adjust the gravity through (gravityMultiplierWhileFalling).
Sin waves to move the player vertically and the horizontal input will be used to move horizontally in the direction previously selected.
Dash
Two types of dashing:
1) Horizontal: Where the player can only dash horizontally on the x-axis during a dash period.
2) Directional: Where the player can freely dash in all 8 directions during a dash period.
There is a flag called (canDashInAir), tick it if you want the player to dash in the air for only one time.
For the dash effect, an after-image style dashing effect is provided out of the box, so you don't need to add any effect as it's the most popular one in many platformer games.
Note: If you choose a long time for the dash to stay active , make sure you have enough amount of instances of the dash effect in the pool. You can as well tick the flag (Expandable) to make sure that always will be enough instances in the pool.
See prefabs/Effects/Dash.
Fire
Fire projectiles have 5 different modes:
Single: As the name suggests, only one projectile gets fired at a time.
Double or triple: Horizontal padding provided to create a space between the projectiles. Note that (horizontalPadding) variable value gets clamped to 1 as maximum value, since a value less than 0 makes no sense and a value greater than 1 will look ridiculous.
Triple spread or quin-triple spread: All projectiles will start from the same position then gradually update their vertical position as specified through the variable (verticalPadding) which again it has been clamped to 1 as maximum value for the same reason declared above. (0.07 or 0.1 is a good value)
Important Notes:
1) In the pool configuration, make sure that the projectile prefab tag matches the name.
2) If more than one prefab has the same tag, then the last configured prefab would be selected. So, you may want to add a unique tag to each projectile prefab if you have more than one.
3) If you use triple spread or quin-triple spread, make sure you have enough projectiles in the pool.
4) If your character has animation clip for shooting, the configuration has been already handled in code, all you have to do is just hook it up in the animator window.
see prefabs/Effects/Projectiles
Grappling Hook
This mechanics is handled using physics constraints (DistanceJoint2D).
1) Get the mouse position in world space.
2) Shoot a ray in the direction of the mouse position, then use the hit point to calculate the distance that would be fed to the distance property of the DistanceJoint2D component.
3) Now simply travels the player along the distance between the player and the object the player grappled with. Determined by the property (MaxDistanceOnly) of the DistanceJoint2D component.
4) Finally, a line renderer with rope material will be used to render the rope.
Additional Features:
1) You have an option to make the player sticks to the platform right after he/she reaches it.
2) You can choose a hook to be displayed at the end of the rope.
See prefabs I have provided multiple hooks which are configured and ready to use, you can rotate and offset them as well.
Note: If you choose to use your own hook sprite make sure to modify the pivot point properly. (Take a look at one of the provided spites).
Bash Ability
The same mechanic in the Ori and the blind forest Game.
Use the mouse or the joystick to aim (An arrow will be spawned and automatically rotated towards the mouse position). Then you can shoot the player in the direction of the mouse position in world space.
Extra: If an enemy or simply an object encounter the player in its shooting direction ( IMPORTANT! Object body must be kinematic at first). Then that object will be pushed against the player shooting direction.
Object has 3 different configurations as follows:
First, if the object is not grounded, then you have 2 options:
1) Dissolve objects on collision. That means while the object is traveling against the player shooting direction if it encounters any platform that has collision then it will dissolve when it collides with it.
2) Dissolve objects After delays. No collision is considered.
Second, if the player is grounded, then the object will be pushed using forces in the opposite direction of the player for a certain period of time (time delay) before it dissolves. Physics constraint will be used to constraint the object, so it moves only on the x-axis.
Animation
I have prepared several animator controllers ready to use just change the animation based on your character animations.
Each animator controller represents a different setup ranges from basic to advanced. Obviously you can as well create your own animator controllers.
No animation for dash is used. Instead a dash after effect is instantiated over a chosen distance during the dash period (As it's the most popular one in many platformer games). This effect is used as well for the bash ability because I couldn’t find any animations that fit this mechanic.
No animation is configured for wall climbing, wall jumping, and grappling hook mechanics, and that is because I couldn’t find any free animation for those on the internet. However, if your character has animation for those mechanics, you can simply add them to your animator controller and then configure them from code. If you need any help, you can send me an email and I will be more than happy to help.