If you want to take over... contact us at os@soom.la
This project is a part of The SOOMLA Framework, which is a series of open source initiatives with a joint goal to help mobile game developers do more together. SOOMLA encourages better game design, economy modeling, social engagement, and faster development.
unity3d-levelup is a library built for easily modeling game structure and user progression, and allows rapid protoyping using a standard and simplified model. It acts as sort of a 'blueprint' for the game, modeling worlds/levels, gates to levels, missions and rewards that can be completed and achieved. All this is backed by SOOMLA's core tools, and can be easily integrated with more SOOMLA modules, like unity3d-store for IAP, or unity3d-profile for social related functions.
unity3d-levelup is the implementation of the LevelUp module for Unity3d.
Generally, the SOOMLA sources contain detailed documentation on the different entities and how to use them, but here's a quick glance:
A Level is pretty clear, and most games have them. A simple example is an Angry Birds single level, where you need to knock out all the pigs. It measures specific things, such as duration it takes to complete, and can be started and ended.
A World is a more general concept than a Level (a Level Is-a World), and can have innerWorlds
to create hierarchies. Another example from Angry Birds is level pages and episodes, which contain the actual levels.
The Initial World is a container world for all worlds and levels in the game. We use the Initial World to intialize the LevelUp module.
A Score is something which can be accumulated or measured within a World (or Level of course). It can be incremented or decremented based on user actions, and recorded at the completion of the World / Level.
This, in turn, can later be applied to high scores or best times, or treated as collectibles that can be awarded upon completion.
A Gate is a closed portal from one World to the next. It can be unlocked in many different ways (according to Gate type), and can also be combined into a GatesList to build more complex Gates.
A Mission is a single task a player can complete in a game, usually for a Reward.
A Challenge is a set of Missions that need to be completed, so it's a big Mission built out of several smaller Missions.
A Reward is some kind of perk or status a player can achieve in the game. This can be either a badge, a virtual item from the game's economy (sword, coins etc.) or anything you can think of, really (unlocking game content or levels comes to mind).
NOTE: LevelUp depends on SOOMLA's other modules: Core, Store, and Profile. This document assumes that you are new to SOOMLA and have not worked with any of the other SOOMLA modules. If this is not the case, and you already have some or all of the other modules, please follow these directions only for the modules you are missing and of course, for the LevelUp module.
-
Clone this repository recursively:
git clone --recursive https://github.com/soomla/unity3d-levelup.git
-
Run
./build_all
from project directory -
You can work with sources, or if you run
deploy/create_deploys
, it will create packages that you can use in your project. -
On the menu bar click "Window -> Soomla -> Edit Settings" and change the value for "Soomla Secret" (also setup Public Key if you're building for Google Play):
- Soomla Secret - is an encryption secret you provide that will be used to secure your data. (If you used versions before v1.5.2 this secret MUST be the same as Custom Secret)
Choose the secret wisely. You can't change it after you launch your game! - Public Key - is the public key given to you from Google. (iOS doesn't have a public key).
- Soomla Secret - is an encryption secret you provide that will be used to secure your data. (If you used versions before v1.5.2 this secret MUST be the same as Custom Secret)
-
Create your own Initial World which should contain all the 'blueprint' of the game (see Model Overview). Initialize LevelUp with the class you just created:
SoomlaLevelUp.Initialize (initialWorld);
Initialize LevelUp ONLY ONCE when your application loads.
Initialize LevelUp in the "Start()" function of a 'MonoBehaviour' and NOT in the "Awake()" function. SOOMLA has its own 'MonoBehaviour' and it needs to be "Awakened" before you initialize.
-
You'll need an event handler in order to be notified about LevelUp related events. refer to the Event Handling section for more information.
And that's it ! You have game architecture capabilities at your fingertips.
To use SOOMLA unit tests in the Other Settings panel of the Player Settings, you will see the Scripting Define Symbols, enter the name “SOOMLA_TEST”. If you are using Unity version older 5.3.0, download NUnit and import to your project.
Please follow the steps in unity3d-store for the Store part of the setup. Then, you can use the store-related LevelUp classes, such as VirtualItemScore or VirtualItemReward or BalanceGate.
Please follow the steps in unity3d-profile for the Profile part of the setup. Then, you can use the profile-related LevelUp classes, such as SocialLikeMission.
SOOMLA lets you subscribe to LevelUp events, get notified and implement your own application specific behavior to those events.
Your behavior is an addition to the default behavior implemented by SOOMLA. You don't replace SOOMLA's behavior.
The Events class is where all event go through. To handle various events, just add your specific behavior to the delegates in the Events class.
For example, if you want to 'listen' to a WorldCompleted event:
LevelUpEvents.OnWorldCompleted += onWorldCompleted;
public void onWorldCompleted(World world) {
Debug.Log("The world " + world.ID + " was COMPLETED!");
}
One thing you need to make sure is that you instantiate your EventHandler
before LevelUp.
So if you have:
private static Soomla.Example.ExampleEventHandler handler;
you'll need to do:
handler = new Soomla.Example.ExampleEventHandler();
before
Soomla.Levelup.SoomlaLevelUp.Initialize (initialWorld);
If you want to see full debug messages from android-levelup and ios-levelup you just need to check the box that says "Debug Messages" in the SOOMLA Settings. Unity debug messages will only be printed out if you build the project with Development Build checked.
Examples using virtual items are dependent on unity3d-store module, with proper
SoomlaStore
initialization andIStoreAssets
definitions. See the unity3d-store integration section for more details.
-
Mission with Reward (collect 5 stars to get 1 mega star)
VirtualItemReward virtualItemReward = new VirtualItemReward("mega_star_reward_id", "MegaStarReward", megaStarItemId, 1); List<Reward> rewards = new List<Reward>(); rewards.Add(virtualItemReward); BalanceMission balanceMission = new BalanceMission("star_balance_mission_id", "StarBalanceMission", rewards, starItemId, 5); // use the store to give the items out, usually this will be called from in-game events // such as player collecting the stars StoreInventory.GiveItem(starItemId, 5); // events posted: // 1. OnGoodBalanceChanged (Store events) // 2. OnMissionCompleted (LevelUp events) // 3. OnRewardGivenEvent (Core events) // now the mission is complete, and reward given balanceMission.IsCompleted(); // true virtualItemReward.Owned; // true
-
RecordGate with RangeScore
Level lvl1 = new Level("lvl1_recordgate_rangescore"); Level lvl2 = new Level("lvl2_recordgate_rangescore"); string scoreId = "range_score"; RangeScore rangeScore = new RangeScore(scoreId, new RangeScore.SRange(0.0, 100.0)); string recordGateId = "record_gate"; RecordGate recordGate = new RecordGate(recordGateId, scoreId, 100.0); lvl1.AddScore(rangeScore); // Lock level 2 with record gate lvl2.Gate = recordGate; // the initial world world.AddInnerWorld(lvl1); world.AddInnerWorld(lvl2); SoomlaLevelUp.Initialize(world); lvl1.Start(); // events posted: // OnLevelStarted (LevelUp events) rangeScore.Inc(100.0); lvl1.End(true); // events posted: // OnLevelEnded (LevelUp events) // OnWorldCompleted (lvl1) (LevelUp events) // OnGateOpened (LevelUp events) // [OnScoreRecordReached] - if record was broken (LevelUp events) recordGate.IsOpen(); // true lvl2.CanStart(); // true lvl2.Start(); lvl2.End(true); // events posted: // OnWorldCompleted (lvl2) (LevelUp events) lvl2.IsCompleted(); // true
-
VirtualItemScore
Level lvl1 = new Level("lvl1_viscore"); string itemId = ITEM_ID_VI_SCORE; string scoreId = "vi_score"; VirtualItemScore virtualItemScore = new VirtualItemScore(scoreId, itemId); lvl1.AddScore(virtualItemScore); world.AddInnerWorld(lvl1); SoomlaLevelUp.Initialize(world); lvl1.Start(); // events posted: // OnLevelStarted (LevelUp events) virtualItemScore.Inc(2.0); // events posted: // OnGoodBalanceChanged (Store events) lvl1.End(true); // events posted: // OnLevelEnded (LevelUp events) // OnWorldCompleted (lvl1) (LevelUp events) // [OnScoreRecordChanged] - if record was broken (LevelUp events) int currentBalance = StoreInventory.GetItemBalance(ITEM_ID_VI_SCORE); // currentBalance == 2
-
Challenge (Multi-Mission)
string scoreId = "main_score"; Score score = new Score(scoreId); Mission mission1 = new RecordMission("record1_mission", "Record 1 mission", scoreId, 10.0); Mission mission2 = new RecordMission("record2_mission", "Record 2 mission", scoreId, 100.0); List<Mission> missions = new List<Mission>() { mission1, mission2 }; BadgeReward badgeReward = new BadgeReward("challenge_badge_reward_id", "ChallengeBadgeRewardId"); List<Reward> rewards = new List<Reward>() { badgeReward }; Challenge challenge = new Challenge("challenge_id", "Challenge", missions, rewards); challenge.IsCompleted(); //false World world = new World("initial_world"); world.AddMission(challenge); world.AddScore(score); SoomlaLevelUp.Initialize(world); score.SetTempScore(20.0); score.Reset(true); // events: // OnMissionCompleted (mission1) (LevelUp events) // [OnScoreRecordReached] - if record is broken score.SetTempScore(120.0); score.Reset(true); // events: // OnMissionCompleted (mission2) (LevelUp events) // OnMissionCompleted (challenge) (LevelUp events) // OnRewardGivenEvent (badgeReward) (Core events) challenge.IsCompleted(); // true badgeReward.Owned; // true
-
GatesList
Note that currently a
GatesList
gate is automatically opened when sub-gates fulfill theGatesList
requirement.
string recordGateId1 = "gates_list_record_gate_id1";
string scoreId1 = "gates_list_score_id1";
double desiredRecord1 = 10.0;
string recordGateId2 = "gates_list_record_gate_id2";
string scoreId2 = "gates_list_score_id2";
double desiredRecord2 = 20.0;
Score score1 = new Score(scoreId1);
Score score2 = new Score(scoreId2);
World world = new World("initial_world");
Level lvl1 = new Level("level1_id");
lvl1.AddScore(score1);
lvl1.AddScore(score2);
world.AddInnerWorld(lvl1);
RecordGate recordGate1 = new RecordGate(recordGateId1, scoreId1, desiredRecord1);
RecordGate recordGate2 = new RecordGate(recordGateId2, scoreId2, desiredRecord2);
List<Gate> gates = new List<Gate>() { recordGate1, recordGate2 };
GatesListOR gatesListOR = new GatesListOR("gate_list_OR_id", gates);
GatesListAND gatesListAND = new GatesListAND("gate_list_AND_id", gates);
SoomlaLevelUp.Initialize(world);
score1.SetTempScore(desiredRecord1);
score1.Reset(true);
recordGate1.IsOpen(); // true
gatesListOR.IsOpen(); // true
gatesListAND.CanOpen(); // false (all sub-gates need to be open for AND)
gatesListAND.IsOpen(); // false
score2.SetTempScore(desiredRecord2);
score2.Reset(true);
recordGate2.IsOpen(); // true
gatesListOR.IsOpen(); // still true
gatesListAND.IsOpen(); // true
SOOMLA appreciates code contributions! You are more than welcome to extend the capabilities of SOOMLA.
Fork -> Clone -> Implement -> Add documentation -> Test -> Pull-Request.
IMPORTANT: If you would like to contribute, please follow our Documentation Guidelines. Clear, consistent comments will make our code easy to understand.
Apache License. Copyright (c) 2012-2014 SOOMLA. http://www.soom.la