Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Help Keeping Track of Player's Team

Discussion in 'Scripting' started by DRRosen3, Oct 14, 2014.

  1. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    So I'm seeking a bit of input here (obviously). I'm working on a project where they player will command units. He will command usually one unit at a time, but later on will be able to control up to three simultaneously. The battle system is a traditional turn-based battle system using a state machine. Here's where I could use some help...

    I'm using a dictionary to store all of the base information for each unit (such as name, race, class, base attack, base defense, etc.). I'm just not quite sure how to keep track (in code) of all of the units that the player has acquired. For example, the player can only have 10 units with him/her at a time. The rest of the units will remain at base until swapped out (similar to how the player could only have 3 characters in his/her party at a time in Final Fantasy VII and VIII).

    Another way to get a good idea of what I'm trying to accomplish is Pokemon. Players/Trainers can only carry six pokemon at a time, and the rest are stored in a PC.

    So along my players journey, he/she will team up with up to 10 characters, and then from there the rest will go to the player's base until called upon. Keep in mind the player can attain multiples of the same type of unit.

    Any ideas?

    P.S. - I'm using C# by the way!
     
  2. novashot

    novashot

    Joined:
    Dec 12, 2009
    Posts:
    373
    Code (CSharp):
    1. List<GameObject> myTeam = new List<GameObject>(); // my team left at home base
    2.  
    3. List<GameObject> mySquad = new List<GameObject>(); // the team I took with me
    add and remove from either list as you swap
     
    ZO5KmUG6R and DRRosen3 like this.
  3. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    Thanks! That (begins) to solve my basic scripting problem. However, how do I solve the problem of having units of the same name? This is a problem when it comes to having let's say five units named "Paratrooper" in the list (mySquad) but only one of them gains experience points. How will the script know which one to apply the experience points to?
     
  4. wccrawford

    wccrawford

    Joined:
    Sep 30, 2011
    Posts:
    2,039
    Use IDs instead of names. Either sequentially created or GUIDs, or some other method, so long as they're unique. You're not going to be showing them to player anyhow.
     
  5. novashot

    novashot

    Joined:
    Dec 12, 2009
    Posts:
    373
    Generally speaking, I also keep that logic not attached to my group formation. Say my squad is killing baddies. The bad guy's health script (in my case) know's this bad guy is taking damage and who is damaging it (my attack script reference whoever is calling attack and send that to whom ever is on the receiving end). When that baddie dies and offers up xp, he has a list of people who have attacked him and who got in the last hit...and I use that reference to send that object xp. My character script keeps track of it's own level and xp and handles the recieving xp call.
     
    DRRosen3 likes this.
  6. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    I think your approach is all wrong on this. A dictionary is not a very good way to keep track of your soldiers. What you need is a soldier class, using polymorphism to make inherited classes that can have different behaviours. This way you have an actual soldier component on each of your soldiers in-game that will allow you to keep it all tied together nicely, without having to worry about duplicated names.
     
  7. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    Hmmm. I'd never heard of GUID's before this. After quickly looking them up I'll have to see about implementing this method. Thanks!

    I had always intended to handle the logic separately, but I just wanted to make sure not to have any errors in sending the exp to the wrong unit, if they have the same names. Thanks to you guys though I think I've got a good start on getting it under wraps.

    I didn't necessarily think my approach was WRONG, per say, however, I have since (the initial post) changed my method from using a dictionary to classes. I have a base class for all units (containing all stats that are shared between all units). From there I created a base class for each individual unit. So basically I have a "BaseUnit" script and derived from that I have "BaseSoldier", "BaseSniper", "BaseSwordsman", etc. These will obviously be attached to the actual model that the player encounters in the over-world. So at this point I just have to implement a way that once each soldier, sniper, swordsman, etc, is added to the players team, they get their own unique ID and the unit is added to the player's inventory/roster/list with exactly the stats the unit had when the player encountered them.
     
  8. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    They don't need any kind of ID if you're using classes for them and treating them in the right way. If your approach requires some sort of unique identifier, there's a better way of doing it. The rest should just follow from creating instances of those classes and setting their variables to what you need. You just need to maintain a list of instantiated soldiers from your classes that have variables for their stats, no real difficulty there.

    Your approach was wrong in that you were using something for a purpose it wasn't intended for and in a non-object-oriented way when there was a much more established and efficient way to do it. There's nothing wrong with approaching something wrong, but there are definitely wrong ways to do things when programming.
     
  9. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    The reason for using the ID is for multiples of the same unit in a list. For example, the player can control 10 units at a time. (For arguments sake let's say the units names are: Private, Captain, and General.) If the player has 5 Private, 3 Captain and 2 General in their party, I need the game to be able to differentiate between which Private, Captain, and/or General gets experience from battle, which one levels up, etc. Unless there's something I'm overlooking, the way to keep track of this is to give each instantiated unit their own ID, right?

    As far as my approach, I'm still a beginner at C# and a novice at programming in general. I really appreciate you making me aware that I was using a programming tool improperly. Only way to grow is to make mistakes and learn from 'em! :)
     
  10. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    Definitely the only way to grow and learn is to make mistakes. Mistakes are good for you, never something to be ashamed of or bothered by.

    Your problem here is that you're thinking like a human. You don't need to be able to personally look at, say, a list of soldiers and be able to identify them, except possibly for debugging. The engine itself is fully aware that each soldier is a discrete individual object, once instantiated.

    The ways to do what you want are through maintaining references. When a bullet is fired, it could have a BaseUnit variable on it that will tell you, on impact, who deserves the experience, if any. You should be able to everything you need to with your soldiers just by maintaining variables that hold references to your soldiers.

    Here's something that may help you understand:
    Code (csharp):
    1.  
    2. BaseUnit soldier1 = new BaseSoldier();
    3. BaseUnit soldier2 = new BaseSoldier();
    4.  
    5. if (soldier1 != soldier2)
    6. Debug.Log("The engine knows which soldier is which, even if all their variables are identical.");
    7.  
     
    DRRosen3 likes this.
  11. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    Alright. I think the only thing I'm not (yet) understanding is the "transfer". The way the player gains units, is by defeating them in battle. Then the unit will find the player worthy, and join their team. In the unit's script (while it's still an enemy) all of its stats are generated at the time it's instantiated. In this way, the chances of getting two units that are a like are near impossible (there are multiple variables I have set up that are used in equations that ensure this). When the battle is over, how do I add the SPECIFIC unit that was generated, to the player's team (List<>)?
     
  12. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    You would do something like this:

    Code (csharp):
    1.  
    2. class BattleManager {
    3.      List<BaseUnit> defeatedSoldiers = new List<BaseUnit>();
    4. // You should have some sort of component on your player object to keep track of this stuff
    5.      PlayerComponent playerComponent;
    6.  
    7.   public void KillSoldier(BaseUnit deadSoldier)
    8.   {
    9.     defeatedSoldiers.Add(deadSoldier);
    10.     deadSoldier.gameObject.SetActive(false);
    11.   }
    12.  
    13.   public void EndBattle()
    14.   {
    15.     foreach (BaseUnit defeatedSoldier in defeatedSoldiers)
    16.     {
    17.       // The player presumably has some sort of list of soldiers available to him
    18.       playerComponent.soldierList.Add(defeatedSoldier);
    19.       // Note that if we didn't remove this soldier from the defeatedSoldiers list, the soldier would exist in both lists.
    20.       defeatedSoldiers.Remove(defeatedSoldier);
    21.     }
    22.   }
    23. }
    24.  
    Note that that's not tested code at all, and just there to give you an idea of the concept.
     
    DRRosen3 likes this.
  13. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    Thanks. I think I get the general idea of how to structure it. I just have one more question though:

    The way I've structured things so far, is that there's a base class for soldiers. Then there's a class that derives from the base class. Finally, I have a script for actually "creating" each soldier (it holds the Create____Soldier(); function). The only way I know how to do "List<>" is to have a database available of all the possible objects to put into that list. However, I'm not sure how to create a database, using the system that I have in place (BaseClass > SubClass > CreateSoldier). Or...do I even need a database?
     
  14. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    The way you're doing the soldiers is perfect. You don't need a database at all. You just need a list of your base class, and thanks to polymorphism, you can put any class that derives from it in your list.
     
  15. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    Sweet! Thanks for all the help! :D