When we implemented the new CRUD operations for storing our monsters in the Inventory, we broke the existing CatchSceneController
script. If you recall, we deleted the old sample CreateMonster
method and wrote a new method to just create a monster entry in the database. This means that not only do we need to fix our updated code, but we also need a way to instantiate new random monster properties.
As usual, before we fix the scene controller, let's address the matter of creating new random monster properties. The ideal solution here is to create a simple static class called a MonsterFactory that will randomly build the monsters. Follow the directions to build our new MonsterFactory
script:
Assets/FoodyGo/Scripts/Services
folder in the Project window. From the context menu, select Create | C# Script. Rename the script MonsterFactory
.using packt.FoodyGO.Database; using UnityEngine; namespace packt.FoodyGO.Services { public static class MonsterFactory { } }
static class
.public static class MonsterFactory { public static string[] names = { "Chef", "Child", "Sous", "Poulet", "Duck", "Dish", "Sauce", "Bacon", "Benedict", "Beef", "Sage" };
public static string[] skills = { "French", "Chinese", "Sushi", "Breakfast", "Hamburger", "Indian", "BBQ", "Mexican", "Cajun", "Thai", "Italian", "Fish", "Beef", "Bacon", "Hog", "Chicken" }; public static int power = 10; public static int level = 10;
CreateRandomMonster
method and helpers:public static Monster CreateRandomMonster() { var monster = new Monster { Name = BuildName(), Skills = BuildSkills(), Power = Random.Range(1, power), Level = Random.Range(1, level) }; return monster; } private static string BuildSkills() { var max = skills.Length - 1; return skills[Random.Range(0, max)] + "," + skills[Random.Range(0, max)]; } private static string BuildName() { var max = names.Length - 1; return names[Random.Range(0, max)] + " " + names[Random.Range(0, max)]; }
Random.Range
in the main method and helpers (BuildName
, BuildSkills
) to provide a random range of values. For the name and skills helper methods, those random values are used as an index into the names
or skills
arrays to return a string value. The random values are then combined into either a name- or comma-separated set of skills.Power
and Level
properties are easily set again using the Random.Range
method. Use a value of 1
, the start, to the maximum property value we set above.CatchSceneController
script in the Unity editor from the Assets/FoodyGo/Scripts/Controllers
folder.Start
method at the top of the file. We will be rewriting the code, as follows:void Start() { var m = MonsterFactory.CreateRandomMonster(); print(m); }
CatchScene
becomes initialized, a new, random monster will be generated.
Example of randomly generated monster properties in the Console
So, now when the CatchScene
starts, random monsters will be created for the player to catch. However, we want the monsters attributes to determine how easy or difficult it is for the player to catch them. What we need to do is add some code that makes the monster more difficult to catch and a way for them to escape. Perform the following to add some difficulty to the CatchScene
:
CatchSceneController
script. Open the CatchSceneController
script from the Assets/FoodyGo/Scripts/Controllers
folder.Awake
method, add the new fields:
public Transform escapeParticlePrefab; public float monsterChanceEscape; public float monsterWarmRate; public bool catching; public Monster monsterProps;
escapeParticlePrefab
will be our particle effect when the monster escapes.monsterChanceEscape
determines the chance of escape. monsterWarmRate
sets how quickly the monster warms after being hit. catching
is just a bool
variable we will use to exit from a loop. Finally, monsterProps
stores the randomly generated monster properties.Awake
method, to the following code:
monsterProps = MonsterFactory.CreateRandomMonster(); print(monsterProps); monsterChanceEscape = monsterProps.Power * monsterProps.Level; monsterWarmRate = .0001f * monsterProps.Power; catching = true; StartCoroutine(CheckEscape());
monsterProps
. Then, as you can see by the code, we derive the escape chance by multiplying the monster's power and level together. After we modify that warm rate by multiplying a base value by the power. (Don't worry too much about the hardcoded .0001f
for now.) Then, we set our catching
state to true
and finally, start a coroutine called CheckEscape
.CheckEscape
coroutine, as follows:
IEnumerator CheckEscape() { while (catching) { yield return new WaitForSeconds(30); if (Random.Range(0, 100) < monsterChanceEscape && monster!= null) { catching = false; print("Monster ESCAPED"); monster.gameObject.SetActive(false); Instantiate(escapeParticlePrefab); foreach (var g in frozenDisableList) { g.SetActive(false); } } } }
CheckEscape
coroutine, there is a while loop that will keep running as long as catching
is true
. The first statement inside the loop yields or effectively pauses the loop for 30
seconds, which means the contents of the while
loop will only run every 30
seconds. After that pause, there is a test to check whether a random value from 0
-100
is less than our monsterChanceEscape
. If it is, and the monster (MonsterController
) is not null, the monster escapes.catching
state to false
, which stops the loop. Next, we print a message to the Console, always a good practice. After this, we disable the monster.gameobject
, instantiate that escape particle, and finally, disable the scene items. In order to disable the scene items, we iterate over the frozenDisableList
.OnMonsterHit
method, enter the new line of code highlighted:
monster = go.GetComponent<MonsterController>();
if (monster != null)
{
monster.monsterWarmRate = monsterWarmRate;
MonsterController
) monsterWarmRate
to the same value we calculated above in the Awake
method.OnMonsterHit
method, add a couple more lines just after the print("Monster FROZEN");
statement, as highlighted:
print("Monster FROZEN");
//save the monster in the player inventory InventoryService.Instance.CreateMonster(monsterProps);
CreateMonster
method when we are adding a new monster to the inventory.escapeParticlePrefab
to the CatchSceneController
.Assets/Elementals/Prebabs(Mobile)/Fire
folder in the Project window, drag the Explosion
prefab into the Hierarchy window and drop it. You will see the explosion particle effect play in the scene.Explosion
object in the Hierarchy window. Rename the object to EscapePrefab and set the Transform component Z position to -3
.EscapePrefab
object into the Assets/FoodyGo/Prefabs
folder to create a new prefab. The reason we created a new prefab is because we changed the default position of the object relative to our scene.EscapePrefab
from the scene by selecting it in the Hierarchy window and pressing the delete key.CatchScene
object in the Hierarchy window. Drag the EscapePrefab
from the Assets/FoodyGo/Prefabs
folder onto the empty Escape Particle Prefab slot on the Catch Scene Controller component in the Inspector window.GameManager
when we wire everything together.Thus far, we now have the MonsterFactory
generating us random monsters. The monster attributes set the difficulty level on the Catch scene. Then, when the monster is caught, we store its attributes in the new InventoryService
within the SQLite database. Sounds like our next task is to build the UI for the Inventory, which we will get to in the next section.
18.222.240.21