Blueless
![Level 4](/v2/img/docs/levels/level03-intermediate_1.5x.png)
Overview
This sample is provided with full source code and demonstrates how Quantum can be used to create a fast and action-packed online 2D platform shooter.
Disclaimer: The sample game was developed by BitCake Studio for Photon Engine.
![](/docs/img/quantum/v2/game-samples/2d-shooter/sample-blueless-splitscreen.png)
![](/docs/img/quantum/v2/game-samples/2d-shooter/sample-blueless-crossplay.png)
![](/docs/img/quantum/v2/game-samples/2d-shooter/sample-blueless-gameplay1.png)
![](/docs/img/quantum/v2/game-samples/2d-shooter/sample-blueless-gameplay2.png)
Download
Version | Release Date | Download | |
---|---|---|---|
3.0.0 | Jul 30, 2024 | Quantum Blueless 3.0.0 Build 435 |
Before You Start
To run the sample in online multiplayer mode, first create a Quantum AppId in the PhotonEngine Dashboard and paste it into the AppId
field in PhotonServerSettings
asset.
Then load the Menu
scene in the Scenes menu and press Play
.
Technical Info
- Unity: 2021.3.30f1.
- Platforms: PC (Windows / Mac), WebGL and Mobile (Android)
Highlights
Technical
- Character Controller 3D with custom steering implementation.
- Raycast projectiles based on delta-movement.
- Data-Driven Polymorphism.
- Respawn Points with Entity Prototypes.
- Disconnect System for inactive players.
Gameplay
- Fast paced, 2D platform shooter.
- Double jump.
- Area damage.
- Grenade.
- Weapon reload time.
- Change weapon using weapon inventory.
Controls
Use A
S
to movement, Space
to jump, Q
E
to change weapon, F
to use the granade, Left Mouse Button
to shoot and use the mouse cursor to aim.
Useful Patterns
Raycast projectiles based on delta-movement
This is a good approach to prevent fast bullets from crossing walls. A raycast based on direction and speed is used to predict the next bullet movement and detect a hit, if any.
C#
Physics2D.HitCollection hits = frame.Physics2D.LinecastAll(bulletTransform->Position, futurePosition);
for (int i = 0; i < hits.Count; i++)
{
var entity = hits[i].Entity;
...
if (entity == EntityRef.None)
{
bulletTransform->Position = hits[i].Point;
// Applies polymorphic behavior on the bullet action
data.BulletAction(frame, bullet, EntityRef.None);
return true;
}
}
Disconnect System
Using the DeterministicInputFlags we check if the player is present. So, the entities of players who are not present for a while are removed from the simulation.
C#
public override void Update(Frame frame)
{
frame.Global->DisconnectTime += frame.DeltaTime;
var robotsFilter = frame.Filter<PlayerID, Status>();
while (robotsFilter.NextUnsafe(out var robot, out var playerID, out var robotStatus))
{
DeterministicInputFlags flags = frame.GetPlayerInputFlags(playerID->PlayerRef);
if ((flags & DeterministicInputFlags.PlayerNotPresent) == DeterministicInputFlags.PlayerNotPresent)
{
robotStatus->DisconnectedTicks++;
}
else
{
robotStatus->DisconnectedTicks = 0;
}
if (robotStatus->DisconnectedTicks >= 15)
{
frame.Destroy(robot);
}
}
}
Back to top