Army Troops
Reminder - Keep Daily Backups
When working on a strategy game with a kit as big as the Complete Kit - always keep a working daily backup! Save yourself the trouble of rolling-back changes and losing work.
What is the army?
When playing battle strategy games you'll always be able to build an army, or heros for battle to attack other player bases and gain in-game resources that you steal from other player bases.
The demo includes a few characters for you to play with, most notably the viking, archer, and mage. Plus we have extra bonus characters premade for developers included in the download center for the highest package kit owners.
About the Shop Menu
Here's a screenshot of the shop menu for your army troops.
Inside the Troops shop menu you can drag and scroll right to see all the units you can built in your game. Click any of the buttons under each unit to begin training.
About the unit training queue
Item From Image Above | Description |
---|---|
Unit production queue | This list fills up from right to left with the units the player is currently training. Each type of unit gets one slot on this bar. |
Prefab image | The image for the unit in the queue shows here |
Remove one unit from queue | Click the (X) to remove one unit from that queue item. If there is only one unit remaining, the queue item is removed and units further up in the queue are moved forward. |
Units remaining | The units remaining to be trained |
Gem cost to finish now | The rare currency cost to finish now. This increases based on the training time remaining. As of now, this is hardcoded into MenuUnit.cs (see below for documentation about gem cost for training times) |
Training progress bar (one unit) | The progress bar under each unit represents the time remaining until one unit is trained. When it completes, the units remaining is decreased by one meanwhile the player's units are increased by one. |
Store Item
All of the store details seen in the below screenshot are taken from the XML/Units.xml file and loaded by Scripts/Units/MenuUnit.cs (details below on what part of the script does this)
From Image Above | Description |
---|---|
Item Name | This is the Name variable |
Time to Build | The TimeToBuild variable (in minutes) . How long the structure will take to to be created. |
Currency Cost | The Price variable. |
Currency Type | The Currency variable (Either Gold, Mana, or Gems) You could change this to whatever currency you will have in your game and also add additional currencies. |
View Description | Shows the Description text variable. |
Prefab Image | The prefab image . |
What happens when a unit finishes production?
When a unit finishes production, they move from the production queue (MenuUnit.cs) to the player's population array. (Stats.cs)
private void FinishObject(int index)
{
int objIndex = ShopController.Intance.ListOfUnitStatusItem[index].QIndex.Objindex;
UpdateExistingUnits(index);
Stats.Instance.UpdateUnitsNo();
UnBuild(objIndex,1);
}
How much does it cost to finish production now for units?
The following excerpt from Scripts/Units/MenuUnit.cs shows the game settings for how the total price is computed in crystals based on the total minutes remaining in the production queue.
For example, if time remaining is less than 30 minutes then it only costs one crystal gem to finish production of all units. Once the total time remaining exceeds 30 minutes but is less than 60 minutes the price increases to 3 crystal gems, and so on.
You can adjust these settings in MenuUnit.cs. Look for the following source code:
if (timeRemaining >= 4320) priceInCrystals = 150;
else if (timeRemaining >= 2880) priceInCrystals = 70;
else if (timeRemaining >= 1440) priceInCrystals = 45;
else if (timeRemaining >= 600) priceInCrystals = 30;
else if (timeRemaining >= 180) priceInCrystals = 15;
else if (timeRemaining >= 60) priceInCrystals = 7;
else if (timeRemaining >= 30) priceInCrystals = 3;
else if (timeRemaining >= 0) priceInCrystals = 1;
What happens when the player accelerates production with a gem?
Once the player clicks the gem acceleration button, a few things happen all at once. First we check if the Player crystal stats is greater than the total crystal price. If not, we show an error. Otherwise we increase the population and erase all the unit data in the training queue array.
public void FinishNow()
{
if (priceInCrystals <= Stats.Instance.crystals)
{
Stats.Instance.crystals -= priceInCrystals;
Stats.Instance.UpdateUI();
ShopController.Intance.UpdateHitText("Training complete.");
IncreasePopulation();
Stats.Instance.UpdateUnitsNo();
EraseValues();
}
else if(timeRemaining > 0)
{
MessageController.Instance.DisplayMessage("Not enough crystals");
}
}
Before Unit Training
Max population size in the below screenshot is 100, meanwhile total army size is 0 and total population size is also 0.
After Unit Training
Menu stats have been adjusted. We still have the same max army capacity (that only increases if you add a building that can store soldier units -- see Shop Menu > Military Buildings) but now we have 19 total army units for a total population size of 49. This is different because some units carry a population size greater than 1. Read more details below.
Item in Image Above | Description |
---|---|
Max Army Capacity | This is the maximum capacity of the player army. The default is 100 set in the GameManager Stats Inspector. The only way it can be increased is if your have buildings with StoreType = Soldiers. Reach the Shop Menu > Military Buildings section for more details or see the Tatami item included in the City Building Kit Demo. |
Actual Total of Units | This is the total number of units. If your game has units that take more than one population space per unit, this number will be different (e.g. 19) than the total population (e.g. 49 as seen in the image above) |
Total Army Size | Some units like the archer take 1 population space. Heavy units like the viking take 3 population space. That's why the total for 19 units can be 49/100 of your army capacity. More details about unit weights below |
How do I expand my army max capacity?
You can read more about this in the Shop Menu > Military Buildings section, however here's a brief summary. Some buildings in your game can increase your total soldier unit population. In the City Building Kit example we provide one of them for you to try. Look at the Assets/CityBuildingKit/Resources/Assets/MilitaryCategory.asset --> Tatami building.
Other than resource generators and storage buildings - you can also store units in your structure to give the player a bigger maximum army size. The ScriptableObject sections in Shop Menu > Military Buildings describes more about this.
UnitCategory.asset Example
Here's an example of one of the unit items included in the City Building Kit UnitCategory.asset (ScriptableObject) file The most important item in this list to observe is that the StoreType is Distributed and StoreResource is set to Soldiers.
A closer look at UnitCategory ScriptableObject (SO)
If you look closely in the above SO, you'll see the green alien character costs 50 of of the Mana currency. You could use whatever currency you want in your game, in the demo we have two placeholders called Gold and Mana. (Plus one rare currency called Crystal Gems)
Units also get a population size. In the example above it's 1.
Size could be any integer value as long as it's less than your army max capacity. For example, you could have 15 archers with a population weight of 1 each or 5 vikings who each have a population weight of 3 for a total army size of 15 (Total unit count is less in the latter, and larger in the former army size).
This is incredibly useful for building games with heavy units like tanks, horses, or heros who may have a huge HP value of 1,000 but take an incredible 10 or 15 population space per unit. Population space is one way that adds extra strategy to your gameplay.
Also, for units, like defense structures and buildings they need an HP health value for battle. You can enter whatever value you want (integer), by default we use 200.
As of the 6.0 version release, the Life value is not used in the development copy but instead life is hardcoded into the Scripts/Units/FighterController.cs file as seen below:
// excerpt from FighterController.cs
private int maxLife = 100,//for progress bar percentage
curPathIndex;
Calculation of hit damage from buildings is done further in Scripts/Units/FighterController.cs where each hit takes 25 HP away from maxLife. If life is == 0, the unit is terminated from gameplay.
// Excerpt from FighterController.cs
// Function calculates attack damage and death of units
public void Hit(int damagePoints, Action callback)
{
life -= damagePoints;
if (callback != null)
{
callback();
}
if (life > 0)
{
healthBar.Value = life / (float)maxLife;
}
else
{
Destroy (gameObject);
}
}
Another SO parameters examples for Units (UnitCategory.asset)
You'll notice the only major change is that Life is larger and population Size is 4 times as much.
MenuUnit.cs - Where the SO data is loaded into
In Scripts/Units/MenuUnit.cs the soldier data from your SO file (seen above) is loaded using a common system used also for all other buildings. Here's an excerpt from MenuUnit.cs of the SO (UnitCategory.asset) data load:
private void UpdateData()
{
List<UnitCategoryLevels> unitCategoryLevels = ShopData.Instance.UnitCategoryData.category;
List<UnitCategory> unitCategoryData = unitCategoryLevels.SelectMany(level => level.levels).Where(c => c.level == 1).ToList();
for (int i = 0; i < unitCategoryData.Count; i++)
{
trainingTimes[i] = unitCategoryData[i].TimeToBuild;
sizePerUnit[i] = unitCategoryData[i].size;
//in case user exits before passing the info to unit proc - MenuUnit is open
unitProc.trainingTimes[i] = trainingTimes[i];
unitProc.sizePerUnit[i] = sizePerUnit[i];
}
}
What happens when the buy button is clicked for a unit?
When the player clicks one of the buttons to train the first unit listed in the store, this function is triggered:
public void BuyStoreItem(UnitCategory itemData, Action callback)
{
if (itemData == null)
{
return;
}
rebuild = false;
bool canBuild = true;
if(itemData.Currency == CurrencyType.Gold)
{
if(!Stats.Instance.EnoughGold(itemData.Price))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Insufficient gold.");
}
}
else if(itemData.Currency == CurrencyType.Mana)
{
if(!Stats.Instance.EnoughMana(itemData.Price))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Insufficient mana.");
}
}
else
{
if(!Stats.Instance.EnoughCrystals(itemData.Price))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Insufficient crystals.");
}
}
if(trainingIndexes[itemData.GetId()] == GameUnitsSettings_Handler.s.maxUnitsNo)
{
canBuild = false;
MessageController.Instance.DisplayMessage(GameUnitsSettings_Handler.s.maxUnitsNo.ToString()+" units limit.");
}
if(Stats.Instance.occupiedHousing + itemData.size>(Stats.Instance.maxHousing))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Increase your soldier housing capacity.");
}
if (canBuild)
{
if(itemData.Currency == CurrencyType.Gold)
{
Pay (itemData.Price, 0, 0);
}
else if(itemData.Currency == CurrencyType.Mana)
{
Pay (0, itemData.Price, 0);
}
else
{
Stats.Instance.crystals -= itemData.Price;
Pay (0, 0, itemData.Price);
}
Stats.Instance.experience += itemData.XpAward;
if(Stats.Instance.experience>Stats.Instance.maxExperience)
Stats.Instance.experience=Stats.Instance.maxExperience;
Stats.Instance.occupiedHousing += itemData.size;
Stats.Instance.UpdateUI();
callback();
Build (itemData.GetId());
//AddUnitInfo(itemData.id, itemData.level);
}
}
Verify Conditions
Can the player train this unit? In Scripts/Units/MenuUnit.cs the BuyStoreItem() -script above- determines if the following conditions are met and canBuild is set to true.
Test #1 - Do they have enough funds?
The first test the player data must pass is their funds - do they have enough of the currency the unit requires to be trained?
if(itemData.Currency == CurrencyType.Gold)
{
if(!Stats.Instance.EnoughGold(itemData.Price))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Insufficient gold.");
}
}
else if(itemData.Currency == CurrencyType.Mana)
{
if(!Stats.Instance.EnoughMana(itemData.Price))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Insufficient mana.");
}
}
else
{
if(!Stats.Instance.EnoughCrystals(itemData.Price))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Insufficient crystals.");
}
}
Test #2 - More than established limit of units of the same type in the training queue?
In the City Building Kit each type of unit can have a certain number of units in the training queue at once. You can adjust this value simply by changing the variable "maxUnitsNo" into the GameUnitSettings file. (Assets/CityBuildingKit/Resources/Assets/GameUnitsSettings.asset)
if(trainingIndexes[itemData.GetId()] == GameUnitsSettings_Handler.s.maxUnitsNo)
{
canBuild = false;
MessageController.Instance.DisplayMessage(GameUnitsSettings_Handler.s.maxUnitsNo.ToString()+" units limit.");
}
Test #3 - Check army population capacity
The last test to pass before units can be deployed is if the player's total unit population has been reached. This test ensures the player can't build more units than they can house.
// Have enough space left in your army population capacity?
if(Stats.Instance.occupiedHousing + itemData.size>(Stats.Instance.maxHousing))
{
canBuild = false;
MessageController.Instance.DisplayMessage("Increase your soldier housing capacity.");
}
If all tests pass, greenlight training.
If the player's data passes all 3 tests and canBuild still is set to true, then the script adjusts the player data awarding the XP they get from the SO file (if any) and deducting the costs involved from the building currency and price.
if (canBuild)
{
if(itemData.Currency == CurrencyType.Gold)
{
Pay (itemData.Price, 0, 0);
}
else if(itemData.Currency == CurrencyType.Mana)
{
Pay (0, itemData.Price, 0);
}
else
{
Stats.Instance.crystals -= itemData.Price;
Pay (0, 0, itemData.Price);
}
Stats.Instance.experience += itemData.XpAward;
if(Stats.Instance.experience>Stats.Instance.maxExperience)
Stats.Instance.experience=Stats.Instance.maxExperience;
Stats.Instance.occupiedHousing += itemData.size;
Stats.Instance.UpdateUI();
callback();
Build (itemData.GetId());
//AddUnitInfo(itemData.id, itemData.level);
}
Updated less than a minute ago