• 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 MKayJay · Nov 01, 2013 at 10:17 PM · runtimemathskills

How to maintain a "learning by using" skill system

I am in the process of writing my own skill system for a game, but I am having a hard time figuring out a good structure. The skill system is fairly simple, the skills have a minimum level of 1 and a maximum of 100, and are leveled simply by using them. I'm using a simple formula that makes the skill levels increase slower as the skill goes higher : x = (y/b)^(1/a) - Where x is the skill level, and y is the required xp, and a and b are constants.

My question is: Should I keep a variable storing the skill level, and then have a separate variable storing the xp, or would it be okay simply to calculate the skill at runtime based on the xp, every time it's needed? (Which could be pretty often). By calculating it I mean simply getting the skill level by calling a property that returns (y/b)^(1/a).

Thanks for reading!

Comment
Add comment · Show 1
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 RyanZimmerman87 · Nov 01, 2013 at 11:13 PM 0
Share

I personally save a PlayerPref for both the XP total and the player's level. But I don't always refer to the PlayerPref every time these variables are accessed. I have a seperate public static variable for both of them that is set on Awake() based on the PlayerPref value.

So you can do all your conditional logic check on the normal variables which should be faster than PlayerPrefs. And then you only deal with setting the PlayerPrefs for gaining a level or XP when the event actually occurs at which time you set the normal variable first and then set the PlayerPref to that value.

As long as you are only using these values when you start a scene or gain XP (not every update frame) I think the processing impact should be fairly $$anonymous$$imal. So just set up unique functions that are only called once like when the enemy dies for example.

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Huacanacha · Nov 01, 2013 at 11:03 PM

This comes down to programmer preference as much as anything... a fairly simple calculation like this doesn't really need to be cached but it doesn't hurt if as you say this could be accessed very frequently (i.e. more than a few times per frame). If the performance impact is minimal either way go with whatever keeps the code cleanest!

One option to consider, if accessing the Skill value is erratic and calculation is costly, is deferred calculation:

 private int _skill = 0;
 public int Skill {
   get {
     if (_skill <= 0) {
       _skill = // Your XP->skill calculation here!
     }
     return _skill;
   }
   private set {_skill = value;}    
 }

You would set Skill to 0 whenever XP changes so that Skill is only re-calculated the first time it is accessed after an XP update.

Comment
Add comment · Show 1 · Share
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 MKayJay · Nov 02, 2013 at 12:11 AM 0
Share

I really like this solution. It fits my needs exactly. Only recalculating the skill whenever xp has changes - Brilliant! Thanks a lot, this is definitely something I can use in other situations as well.

avatar image
0

Answer by RyanZimmerman87 · Nov 01, 2013 at 11:40 PM

I'll do a quick little example of how I handle this kind of thing since I already have in my project and might be useful reference for people starting up on these kinds of systems.

 //these aren't really the #'s I use just example
 //I think it's probably better to just have the XP totals set on awake()
 //that way you don't have to do a bunch of formula calculations every time you gain XP
 //should probably just use an array for this to more easily handle it
 //could probably just load all 100 XP levels (or a reasonable # of levels based on current level)
 //in the array once per scene
 
 float level1XP = 50; 
 float level2XP = 100;
 
 //variables to store relevant data
 
 public static int playerCurrentLevelInt;
 float playerCurrentXPRequired;
 float playerLastXPRequired;
 
 //create a public static Instance to easily access
 //local XP functions from any other script
 public static PlayerXPScript XPInstance;
 
 //use start or Awake
 void Start() 
 {
 //some other stuff you need
 
 //get player prefs for XP and player level
 //in my game these are actually stored in another script called GlobalDataScript
 playerXPTotal = PlayerPrefs.GetFloat ("XP Total", 0);
 playerLevel = PlayerPrefs.GetInt ("Player Level", 1);
 
 
 //get instance ready
 XPInstance = GetComponent<PlayerXPScript>();
 }
 
 //use our instance to easily access the local XPUpdateFunction
 //from any script in our project
 public static void XPUpdateCall()
 {
 XPInstance.XPUpdateFunction();
 }
 
 //function where all the xp calculations and updates take place locally
 void XPUpdateFunction()
 {
 //this part could probably be improved
 //but it gets the job done and is fairly simple anyways
 
 //checks what level the player is each time function is called
 if (GlobalDataScript.playerXPTotal < level1XP)
 {
 playerCurrentLevelInt = 1;
 
 playerCurrentXPRequired = level1XP;
 playerLastXPRequired= 0;
 }
 
 //checks what level the player is each time function is called            
 if (GlobalDataScript.playerXPTotal >= level1XP)
 {
 playerCurrentLevelInt = 2;
 
 playerCurrentXPRequired = level2XP;
 playerLastXPRequired = level1XP; 
 }
 
 //repeat the above process or use an improved system
 //until you know what level you are after the current XP update
 
 //then get what level you currently are according to PlayerPref
 //excessive since you should already know but whatever I'll eventually
 //rewrite my system
 int playerLevelInt = PlayerPrefs.GetInt ("Player Level", 1);
 
 //if you have more xp than level 1 MAX
 if (GlobalDataScript.playerXPTotal >= level1XP)
 {
 
 //if you still are level 1 then update everything so you are level 2
 if (playerLevelInt==1)
 {
 PlayerPrefs.SetInt ("Player Level", 2);
 GlobalDataScript.playerLevel = 2;
 GlobalDataScript.playerStatPointsAvailable +=  2;
 PlayerPrefs.SetInt ("Player Stat Points", GlobalDataScript.playerStatPointsAvailable);
 GlobalDataScript.playerSkillPointsAvailable += 2;
 PlayerPrefs.SetInt ("Player Skill Points", GlobalDataScript.playerSkillPointsAvailable);
                 
 levelUpNotificationFunction();
 }
 }
 
 //if you have more xp than level 2 MAX
 if (GlobalDataScript.playerXPTotal >= level2XP)
 {
 
 //if you still are level 2 then update everything so you are level 3
 if (playerLevelInt==2)
 {
 PlayerPrefs.SetInt ("Player Level", 3);
 GlobalDataScript.playerLevel = 3;
 GlobalDataScript.playerStatPointsAvailable +=  2;
 PlayerPrefs.SetInt ("Player Stat Points", GlobalDataScript.playerStatPointsAvailable);
 GlobalDataScript.playerSkillPointsAvailable += 2;
 PlayerPrefs.SetInt ("Player Skill Points", GlobalDataScript.playerSkillPointsAvailable);
                 
 levelUpNotificationFunction();
 }
 }
 
 }


So by using that instance you can easily call this function from any other script with 1 line of code. For example this could be on an enemy script:

 if (XPUpdateBool == false)
 {
 XPUpdateBool = true;
 PlayerXPScript.XPUpdateCall();
 }

Once you call it from enemy script in the PlayerXPScript it does a check to see what level you are currently based on XP total. And then once it has that it checks to see if you have enough XP for next level but haven't yet reached it and if so updates all your stats and saves PlayerPrefs.

It's a bit of messy system the way I did this so I'll probably make some improvements once the player can start hitting high levels. But that should hopefully be a pretty nice and simple outline of logic for people learning this for the first time.

Comment
Add comment · Share
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

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

17 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

Related Questions

Export objects to a .3DS file at runtime 1 Answer

problem with mathf.tan 2 Answers

Need a little help with quick angle equation 2 Answers

CharacterController on Moving Surface 4 Answers

Make something move away from click point. 2 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