Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by ivarhill · Mar 04, 2019 at 04:22 PM · c#listclassframeworkstructure

Best structure for a perk system?

I got a game that makes use of a simple perk system. There is a list of "perks" and every time the player levels up the game should generate a list of a random 3 that the player can choose from. Here's a few examples of perks to give a basic idea:


  • Healthy - Increases your maximum life to 150.

  • Vigorous - Increases your maximum life to 200. (Requires "Healthy")

  • Health Regeneration - While detected by an enemy, you regenerate 1 health per second.

  • Heavy Armor - You no longer take damage from enemy death explosions.

  • Shielded - You gain a shield which can absorb damage and recharges automatically.


Some perks require others to already have been picked before they can get randomized, and a lot of perks has values that I'll want to tweak for balance purposes.

With all of this in mind, I've been making a PerkManager class that handles all of this, but I'm not quite sure of the best way to structure it up. It makes sense, I think, to have a Perk class which would look like the following:

 public class Perk
 {
     public string name;
     public string description;
     public bool picked = false;
     public Perk requiredPerk;
     public List<int> values;
 }

Name/description are self-explanatory, picked determines whether the perk has been picked by the player, requiredPerk is, when needed, a reference to the instance of the other perk that would need "picked" set to true for it to appear, and values is a list of integers - set up here so that it's easy for me to balance the perks right in the PerkManager.

I then have a List that I would fill with Perk objects:

 public List<Perk> perks = new List<Perk>();

This list would be read from to generate another list of eligible perks to be picked when the player levels up.


The main issue here is that I'm not sure of the best way to initialize the large number of Perk objects. I can do a simple initialization as such:

 public Perk perkHealthy = new Perk();
 public Perk perkVigorous = new Perk();

And then declare the perk info at start, which sets all the perk info and also adds each perk to the perks list.

 void Start()
     {
         //Healthy
         perkHealthy.name = "Healthy";
         perkHealthy.description = "Increases your maximum life to {0}.";
         perkHealthy.values.Add(50); //Extra health given
         perks.Add(perkHealthy);
 
         //Vigorous
         perkVigorous.name = "Vigorous";
         perkVigorous.description = "Increases your maximum life to {0}.";
         perkVigorous.requiredPerk = perkHealthy;
         perkVigorous.values.Add(100); //Extra health given
         perks.Add(perkVigorous);

This works, but it seems a bit clumsy. I could of course also set Perk to serializable and enter all this information directly as members of 'perks' in the Unity editor, but I wanted to avoid this since I want these values to be inherent values of the class rather than tied to a specific instance of PerkManager.


Alternatively I can do it all at start, by first adding this to Perk:

 public Perk(List<Perk> perkList = null)
     {
         if(perkList != null)
             perkList.Add(this);
     }

And then at start:

 void Start()
     {
         Perk perkHealthy = new Perk(perks)
         {
             name = "Healthy",
             description = "Increases your maximum life to {0}.",
             values = { 50 }
         };
         Perk perkVigorous = new Perk(perks)
         {
             name = "Vigorous",
             description = "Increases your maximum life to {0}.",
             requiredPerk = perkHealthy,
             values = { 100 }
         };

This is a bit more elegant since there's only a single place I can declare all perks in order - but it has the huge disadvantage of the perks not being public and as such not being easily accessible - unless there's a simple way to refer to a specific instance in a List<> that I am not aware of? From what I understand I'd basically have to search the perks List for name or something similar every time I want to refer to a specific perk, which seems bad on performance.

I wish I could just do the above at the top of the class itself so that I can set the perk objects to public, but that wouldn't work since 1) I can't populate the list outside a function, and 2) I can't refer to these newly declared objects for requiredPerk at declaration - so then I'd still have to separately do these things in Start() in which case the very first solution is probably better.


Finally, a third solution might be to declare the perks List<> with all perks right away, and instead of making these instances just rely on a new "perkID" field which acts as its identifier and is used for things like finding it in the list or looking up a requiredPerk. But I don't really know if this is good practice or not.

Does anyone have thoughts of what would be the best way to structure up this?

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image WarmedxMints · Mar 04, 2019 at 04:38 PM 0
Share

Personally, I would probably either use ScritptableObjects and/or have a base class with virtual methods and derive from that. If the values for these pickups are constant, scriptableobjects are likely a good way to go.

avatar image ivarhill WarmedxMints · Mar 04, 2019 at 04:57 PM 0
Share

Thanks for the reply!

I'm guessing I'd have to use a combination of both since the unique values per perk differ a lot (see https://answers.unity.com/questions/1608866/inheritance-best-solution-to-handle-many-instances.html for details on that, it's a bit of a separate question/issue).

Nonetheless, I will look into the use of ScriptableObjects, thanks for that suggestion!

avatar image RobAnthem · Mar 04, 2019 at 05:54 PM 0
Share

Alternatively you could do something like this

 public class Perk$$anonymous$$anager : ScriptableObject
 {
 #if UNITY_EDITOR
     [UnityEditor.$$anonymous$$enuItem("Tools/New Perk manager")]
     public static void CreateNewPerks()
     {
         UnityEditor.AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<Perk$$anonymous$$anager>(), "Assets/Resources/" + PerkResourceHash + ".asset");
     }
 #endif
     private static Perk$$anonymous$$anager instance;
     private const string PerkResourceHash = "perks";
     [System.Serializable]
     public class Perk
     {
         public int id;
         public string Name;
         public string Desc;
         public float baseValue;
         public GameObject somePerkObject;
         public Sprite Icon;
         public Something someField;
     }
     public List<Perk> perks;
     public static Perk GetPerk(int id)
     {
         if (instance == null)
             instance = Resources.Load<Perk$$anonymous$$anager>(PerkResourceHash);
         return instance.perks[id];
     }
     public static Perk GetPerk(string Name)
     {
         if (instance == null)
             instance = Resources.Load<Perk$$anonymous$$anager>(PerkResourceHash);
         foreach (Perk perk in instance.perks)
         {
             if (perk.Name == Name)
             {
                 return perk;
             }
         }
         return null;
     }
 }

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

591 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

C# List and GUI 3 Answers

How to sum a property of a class in a List 2 Answers

Can't call derived class function from list of base class. Ideas? 1 Answer

Need my function to work with different lists of different values (classes) 1 Answer

Requesting help utilizing resources.load to auto assign rigidbody variable in a class list 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges