- Home /
how to add a function to Leveling a Character useing the Fibonacci sequence?
my current code for my character lvling system is very basic
public float Xp = 0f; //floats can be used for later lvls so gathering xp takes longer
public float Health = 100f;
public int Level = 1; // i believe it makes since to start off as one instead of zero
public float XpToNxtLvl = 0f;
public int FibonacciLevel = 0;
XpGain(float amount )
{
Xp += amount;
if( Xp >= XpToNxtLvl)
{
NextLvl();
}
}
NextLvl()
{
XpToNxtLvl += 1100;
Health += 50;
}
new formula
fn = fn-1 + fn-2 would i make n (Level+1) and f (XpToNxtLvl) is it that easy?
(FibonacciLevel+1))-1 + (FibonacciLevel+1))-2
old formula
XpToNxtLvl += ((XpToNxtLvl (Level + 1)) - 1 + (XpToNxtLvl (Level + 1)) - 2);
my Answer
XpGain(float Fibonacci)
{
Xp += Fibonacci;
if( Xp >= XpToNxtLvl)
{
NextLvl();
}
}
NextLvl()
{
FibonacciLevel = Level +1;
XpToNxtLvl += ((FibonacciLevel-1) + (FibonacciLevel-2))
Health += 50;
Level += 1;
}
I believe there could be some mistakes which is why I'm posting this question thank you for your time reading this sorry if its long i appreciate any feedback
theres another post about an infinte lvl system http://answers.unity3d.com/questions/973992/infinite-level-system.html
who makes use of a private multiplier variable would it make since to turn the fibonacci formula instead into a private variable? the basic code is from a couple of rpg tutorial series i was using to learn from so since it not my own other than variable changes ill just say i got it from the HardlyBriefProgramming series as well as naman jain both on youtube.
I notice that the Fibonacci sequence is very similar in SHAPE, on a graph, to an exponential function. Why not keep it simple and just use something like that e.g. squared: levelXP = 100.0f * level*level;
an exponential function would be something like XpToNxtLvl = mathf.pow(100,Level)*level; is my assumption wrong?
tho there are a couple inaccuracies but not nearly as many as i was getting. using that function i actually got pretty accurate results thank you for your knowledge.
X to the power of two ( Pow(X,2) )is equivalent to X * X
X to the power of three( Pow(X,3) ) is equivalent to X*X*X
Pow(100,Level) mean 100 to the power of "Level" (or 100*100*...*100, "Level" times)
If a function has a power of two or greater, it is considered an "exponential function". $$anonymous$$ost relevantly; when you look at a graph of an exponential function, it is NOT a straight line.
Answer by Bunny83 · Aug 10, 2016 at 12:46 AM
You don't seem to understand what that formula stands for. It's a "recurrence relation". The "f" in fn = fn-1 + fn-2 doesn't stand for a constant. "fn" stands for a particular number in the sequencem specifically the "nth" number. The fibonacci sequence is a common example for recursion, however it's quite inefficient to use a recursion for calculating the sequence.
public static int Fib(int aIndex)
{
if (aIndex <= 0) // important, breaking condition for the recursion
return 0;
if (aIndex == 1) // important, breaking condition for the recursion
return 1;
return Fib(aIndex-1) + Fib(aIndex-2); // recursion
}
This function will return the nth fibonacci number. So if you call
Fib(10);
it will return "55" the "10th" fibonacci number:
n Fib(n)
----------
0 - 0
1 - 1
2 - 1
3 - 2
4 - 3
5 - 5
6 - 8
7 - 13
8 - 21
9 - 34
10 - 55
As i said calculating the fibonacci sequance recursively is quite inefficient, It's easier to calculate it iterative
public static int Fib(int aIndex)
{
int n1 = 0;
int n2 = 1;
for(int i = 1; i < aIndex; i++)
{
int tmp = n1 + n2;
n1 = n2;
n2 = tmp;
}
return n1;
}
This does the same but without recursion.
In your case instead of storing only "XpToNxtLvl" you could store the last two numbers instead of the last one. So basically when you level up you just do "one iteration" of the for loop yourself to get the next number in the sequence. Of course you could use the "Fib()" method to calculate a certain fibonacci number, but for higher numbers it's unnecessary to count up from the very beginning if you can simply store the last two numbers instead.
edit
Here's a class that automatically builds a lookup table for Fibonacci numbers:
using UnityEngine;
using System.Collections.Generic;
public class Fib
{
public static Fib Global = new Fib();
private List<int> m_Numbers = new List<int>();
public Fib()
{
m_Numbers.Add(0);
m_Numbers.Add(1);
}
public int this[int aIndex]
{
get { return GetNumber(aIndex); }
}
public int GetNumber(int aIndex)
{
if (aIndex < 0)
throw new System.ArgumentOutOfRangeException("aIndex must be positive");
if (aIndex >= m_Numbers.Count)
GenerateUpTo(aIndex);
return m_Numbers[aIndex];
}
private void GenerateUpTo(int aIndex)
{
for(int i = m_Numbers.Count; i <= aIndex; i++)
{
m_Numbers.Add(m_Numbers[i-2] + m_Numbers[i-1]);
}
}
}
You can create an instance of that class somewhere (and store it for later use) or use the static "Global" instance. Of course the "Global" instance is not thread-safe. To get a certain number you can simply do:
int xp1 = Fib.Global[8]; // returns 21
int xp2 = Fib.Global[34]; // returns 5,702,887
Keep in mind that a signed 32 bit integer can only represent the fibonacci numbers up to "level" 46. The 47th number is 2,971,215,073
and a signed integer only goes up to "`2,147,483,647`".
Even when using "ulong" as type (unsigned 64bit integer) you can only go up to fib number 93 which is 12,200,160,415,121,876,738
It depends on how "accurate" you actually need them to be. Of course you can exchange "int" with "double" in my class which gives you a much larger range, but the numbers quickly get inaccurate. If you just need "some level" that's probably fine. However keep in mind when using floating point numbers the higher the number gets, the greater the smallest representable amount will be. So at high numbers you can't add small amounts to that number.
thank you for your feedback. i was going to do it that way but i was thinking that if i could just have the Fibonacci number ins$$anonymous$$d of saving previous ones it would be more useful. i think i got the fix to my formula.
XpToNxtLvl = ((1+$$anonymous$$athf.Pow($$anonymous$$athf.Sqrt(5f),Level)) - (1f-($$anonymous$$athf.Pow($$anonymous$$athf.Sqrt(5f),Level)))) /($$anonymous$$athf.Pow(2,Level) $$anonymous$$athf.Sqrt(5f); the formula on paper is ((1+5√)^n−(1−5√)^n)/(2^n5√) im not at my computer atm so i cant see if it will work but on paper it seems to be working.
Yes, you can use the golden-ratio formula but it has a little flaw in computer math when using floating point numbers. It works great for the lower fibonacci numbers but might fail for larger ones. First problem is the limited floating point accuracy. The second problem is that "Pow" with high powers can be quite demanding.
Since you would store "XpToNxtLvl" as well as your current "index" of the fibonacci number, you could ins$$anonymous$$d store the two last fibonacci numbers and can instantly move to the next.
btw: There's also a way to advance to the next number without a temp variable:
n2 += n1; // n2new = n2old + n1old
n1 = n2 - n1; // n1new = (n2new - n1old) == (n2old + n1old - n1old) == n2old
If you need to freely access any of the fibonacci numbers randomly i suggest creating a "List" which simply holds the whole sequence which is initialized in the beginning. The List can be made "self growing". I can add an example class to my answer...
well this script started out as a learning process for me. as for the original purpose i was just trying to add a formula to the basic lvl up script i made in a tutorial. so i would not have to write all the code like this lvl 1 xp = this number lvl 2 xp = this number etc... i can understand why you would make a list since its easier to acquire accurate numbers in that manner so its not like i need accurate numbers, but since its a learning process trying to get accurate numbers i feel would help me learn the quirks and mistakes ive made.
questions about your answer 1. ""pow" with high powers can be quite demanding" at what point would it start to be demanding. i can see how a power of 100 would be demanding since it would equal a ridiculously huge number. 2. ""Global" instance is not thread-safe." what do u mean by that 3."If you just need "some level" that's probably fine". true, but lets say that i wanted infinite lvls or a ridiculous amount is the list method of saving fibs and returning the one i want the less intensive way to go about it? 4. a signed integer only goes up to "`2,147,483,647`". whats the differnce between a signed and unsigned interger?
i have no real purpose with this script other than learning a little more of c#. in your method i have a list of two fibs with a function or two that creates the fibs and than returns the fibs that i want while saving the next fib so i can always get the next fib. why is that less demanding than not saving any of the fibs but one the current one as xptonxtlvl when you save the lvl?
thank you for all your time explaining in a clear and concise manner all the information. i was unaware about the integer length was related to 32-64-128 bits signed or unsigned.
edit on a side note i noticed that if i want to continue to use the golden ratio as the formula ill have to make a separate function to acquire phi with the highest number of float points possible to acquire the highest accurate numbers
Answer by Hraesvelgr-tc · Aug 09, 2016 at 07:21 AM
This is the script that I got working as close to Fibonacci numbers as i could for my xp to lvl. i guess i didn't really need to ask this question or maybe it was the wrong question either way it works now.
the script that i made
public float Xp = 0f;
public float XpToNxtLvl = 0f;
public float Health = 100f;
public float StatPoints = 0f;
public float Level = 1f;
public Texture2D button;
// public float FibonacciLevel = 0f;
// onclick event for button
public void OnMouseDown()
{
Xp += 1;
print("+1Xp");
}
// onclickRelease event for button
public void OnMouseUp()
{
XpGain ();
if(Xp >= XpToNxtLvl)
{
print("Level Up!");
}
}
// not sure if this is needed but possible use in future probaly could just combine
// it with nxtLvl function
void XpGain()
{
if( Xp >= XpToNxtLvl)
{
NextLvl();
}
}
// LevelUP!
void NextLvl()
{
Xp -= XpToNxtLvl;
Health += 50;
StatPoints += 10;
Level += 1;
}
// Button and other user interface things
void OnGUI()
{
if (GUI.Button (new Rect (10, 70, 100, 20), "Click"))
{
OnMouseDown ();
OnMouseUp ();
}
}
// Use this for initialization
// void Start ()
// {
// }
// Update is called once per frame
void Update ()
{
// Binets Formula for getting fibonacci numbers aka using the golden ratio
// to get fibonacci numbers
XpToNxtLvl = ((Mathf.Pow(1.618034f,Level)) - (1f-(Mathf.Pow(1.618034f,Level)))) / Mathf.Sqrt(5f);
}
}
the numbers for XpToNxtLvl i get are as follows
upon start .4472136
click once 1
click twice 1.894427
click fifths 3.341641
click thrice 5.683281
click six 9.472136
15.60263
25.52198
41.57183
now fibonacci sequence obviously is 0 1 1 2 3 5 8 13 21
im pretty sure something is wrong still im not sure why it starts off with .4 ins$$anonymous$$d of 0
is it because the decimals exist it's not getting the answer it doesn't work with ints though
new formula fix to try to get more accurate numbers
XpToNxtLvl = ((1+$$anonymous$$athf.Pow($$anonymous$$athf.Sqrt(5f),Level)) - (1f-($$anonymous$$athf.Pow($$anonymous$$athf.Sqrt(5f),Level)))) /($$anonymous$$athf.Pow(2,Level) $$anonymous$$athf.Sqrt(5f)
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Turn Order 2 Answers
Literally just started coding in c#, having error cs1729 1 Answer