Bug Between Encounter System + Enemy Manager (Blank Battle)

So I’ve come across a bug that actually can have major issue when it comes to expanding the game but I don’t know how it would be fixed without basically redoing the entire Encounter system.

The problem is if you put multiple number of “enemys in scene” on the “Encounter System” you then HAVE TO include the EXACT SAME enemys on the “Enemy Manager” as well in the “all enimies” array.

Otherwise what happens is the script will then read and get an enemy from the “Encounter System” but cant find it in the “Enemy Manager” and you will end up in a Blank Battle Scene with 0 enemys

It took me 2 days to figure out what was happening as Unity didnt pop up any errors to this.

So for example in my “Encounter system” i had 2 enemys a “Slime” and a “Buff Slime” but in my “Enemy Manager” i forgot to add “Buff Slime” to the list. so what ended up happening is the Enemy Manager would sometimes Generate 0 enemys for battle because it was trying to get “Buff Slimes” from the “Encounter System” but couldn’t find it in the “all enemys” section of the “Enemy Manager”.

Imo this is really bad for expansion because if you wanna add a list of like 20 enemys to an area but forget to put all those enemys in both list you can end up with problematic encounters. this should really be refactored so that BOTH scripts are pulling from the same list that is initilized ONCE in the Inspector not TWICE.

I don’t have (and so haven’t done) this course, and I’m going by what I see on GitLab.

It sounds like you’ve already found a solution to the main problem: make a script to store the full array of enemies and reference that wherever you need it.

Something like this:

public class EnemyDatabase
{
    public EnemyInfo[] Enemies; // Put all your enemies in here
}

Then in EnemyManager create a Start method in which to get the data:

private void Start()
{
    allEnemies = EnemyDatabase.Enemies;
}

Everything above should work without problems. The following is messier, so make sure you back up your scripts before trying to implement it.

The issue from what I can tell by looking at the code is with the Encounter class included in the same file with EncounterSystem… I don’t know what this looks like in Unity so I’m not sure if you could take the required EnemyInfo directly from the proposed EnemyDatabase. Possibly you could add an index value to it instead of EnemyInfo:

[System.Serializable]
public class Encounter
{
    public int EnemyIndex;
    public int LevelMin;
    public int LevelMax;
}

Then use that index in EnemyManager:

public void GenerateEnemiesByEncounter(Encounter[] encounters, int maxNumEnemies)
{
    currentEnemies.Clear();
    int numEnemies = Random.Range(1, maxNumEnemies + 1);

    for (int i = 0; i < numEnemies; i++)
    {
        Encounter tempEncounter = encounters[Random.Range(0, encounters.Length)];
        int level = Random.Range(tempEncounter.LevelMin, tempEncounter.LevelMax + 1);
        GenerateEnemyByIndex(tempEncounter.EnemyIndex, level); // Using an int here not a string
    }
}

private void GenerateEnemyByIndex(int enemyIndex, int level) // Taking in (int, int) instead of (string, int)
{
    // By using a consistent index it should be possible to skip the for loop

    Enemy newEnemy = new Enemy();

    newEnemy.EnemyName = allEnemies[enemyIndex].EnemyName;
    newEnemy.Level = level;
    float levelModifier = (LEVEL_MODIFIER * newEnemy.Level);

    newEnemy.MaxHealth = Mathf.RoundToInt(allEnemies[enemyIndex].BaseHealth + (allEnemies[enemyIndex].BaseHealth * levelModifier));
    newEnemy.CurrHealth = newEnemy.MaxHealth;
    newEnemy.Strength = Mathf.RoundToInt(allEnemies[enemyIndex].BaseStr + (allEnemies[enemyIndex].BaseStr * levelModifier));
    newEnemy.Initiative = Mathf.RoundToInt(allEnemies[enemyIndex].BaseInitiative + (allEnemies[enemyIndex].BaseInitiative * levelModifier));
    newEnemy.EnemyVisualPrefab = allEnemies[enemyIndex].EnemyVisualPrefab;

    currentEnemies.Add(newEnemy);
}

Again I want to stress that I’m not familiar with the course and the project so I might be missing important information. Even if this does work for the moment, making these changes could easily cause problems following later sections of the course if you haven’t completed it yet. (I think it’s still in early access at this time.) Plus, this idea to use an index number is potentially going to make it more difficult to know which enemies you’re referencing when setting up your scenes. It could definitely be improved, maybe using an enum or something like that.

While this is a valid option, I disagree. I don’t necessarily want an encounter to draw from the full list of enemies, but rather a curated selection that suits the current area. As an example, if I have two areas - one on land and one in water - I don’t really want to be able to choose water monsters in a land encounter (and vice versa).

Like @Satinel, I too have not done this course but it doesn’t make sense for me to just pull any enemy. Judging from @Satinel’s code, there is a way to limit the enemies’ level and it could certainly be modified to also limit the type, but that requires changes to the enemies, etc. Much easier to just have a curated list. I’d add code to log an error when the encounter is trying to create an enemy that doesn’t exist, and then move on and try again with a different enemy (or in my case, pause the game because I have ‘Pause on Error’ turned on). This will let me know an enemy is missing and I can fix that. Forgetting to add a monster to some list is not really something that should silently be ‘dealt with’. You should get an issue so that you can rectify it.

No i understand that being able to have different types of “Encounter” data would be optimal. like create a “Land” list and a “water” list and have the codes pull from those list based on which location data you are in.

The problem though is it feels like this lectures code was built with the idea that you populate your encounter list and have to have the enemy manager also require the same list of Enemys (which to me feels redundant?) and filled with errors if you cant find the enemy on the manager list.

ideally id rather just have the ability to create a Single list that both managers pull from but i was able to slot in what list that would be based on environment. this way it would prevent having to make sure both list have the same enemys.

There is a difference in the data that is being kept within the Encounter System and the Enemy Manager, one holding the EnemyInfo and the other holding an Encounter, which actually contains the enemyInfo as well.

Interestingly enough, we really don’t need the enemies list in the EnemyManager, as the EncounterSystem already passes this information into the EnemyManager
This is the Encounter which is passed to EncounterSystem

public class Encounter
{
    public EnemyInfo Enemy;
    public int LevelMin;
    public int LevelMax;
}

Which means our EnemyManager already has the info it needs in GenerateEnemiesByEncounter.
This means that instead of GetEnemyByName(), we can write a simpler function

private void GenerateEnemy(EnemyInfo enemyInfo, int level)
{
    Enemy newEnemy = new Enemy();
    newEnemy.EnemyName = enemyInfo.EnemyName;
    newEnemy.level = Level;
    float levelModifier = (LEVEL_MODIFIER * newEnemy.Level);
    //rest of method, using enemyInfo instead of allEnemies[i]
}
1 Like

Privacy & Terms