0

Hi I'm a unity developer working on a bar manger game and I'm just wondering on the best way to implement a drinks system where it sets the value of the drink, number of servings in the barrel, name of the drink price of the whole barrel.

Here is some code I was working on before:

This is the interface method

public interface IDrinkSystem
{
    string SetDrinkName(string nameToSet);
    float SetDrinkValue(float drinkValue);
    int AmmountOfServingsInBarrel(int Servings);
    float PriceOfBarrel(float price);
}

This is the class method of doing it

public class DrinkSystem 
{
    public void NewDrink(string drinkName, float drinkValue, int barrelServings, float barrelPrice)
    {
     // Have getters and setters for all values in separate methods   
    }
}

What is the best way for making it easy to expand and at a push can I make an array of the NewDrink to store all the drinks i have or is there abetter way of doing this.

  • 1
    Side note: I would use decimal instead of float for better accuracy. – HardcoreGamer Jul 06 '21 at 09:18
  • @HardcoreGamer it does but in the OPs use case it isn't needed, I expect even the `IDrinkSystem`s floats are whole numbers anyway, at best 2 decimals deep for the value/price – akaBase Jul 06 '21 at 09:40
  • @akaBase I should not have use the word "accuracy" which may caused confusion. What I meant is that It is fine to use float if the number will only be used internally for settings and etc. The number OP is using will likely be displayed somewhere in order menu. Use decimal will save you a lot of time wasted on rounding. FYI: https://stackoverflow.com/questions/588004/is-floating-point-math-broken – HardcoreGamer Jul 06 '21 at 10:04
  • @HardcoreGamer thats why in Unity I use `Mathf.Abs(val1 - val2) > float.Epsilon` to check if the value is equivlant to 0f – akaBase Jul 06 '21 at 10:09
  • 2
    @akaBase and why don't you simply use the Unity built-in [`Mathf.Approximately(val1, val2)`](https://docs.unity3d.com/ScriptReference/Mathf.Approximately.html) which does basically the same? ^^ – derHugo Jul 06 '21 at 13:56
  • @derHugo I hadn't seen it :D – akaBase Jul 06 '21 at 14:14
  • @HardcoreGamer almost everything in Unity uses `float` which is mostly enough precision. OP is not implementing some highly reliable banking system but rather a simple game ^^ – derHugo Jul 06 '21 at 14:34
  • @derHugo Understandable. Btw that's the first time I see this float.Epsilon as well : ) – HardcoreGamer Jul 07 '21 at 01:38
  • @HardcoreGamer the latter is not a Unity thing but c# itself actually ;) [`Single.Epsilon`](https://learn.microsoft.com/dotnet/api/system.single.epsilon) – derHugo Jul 07 '21 at 14:23
  • @derHugo Thanks a lot for the docs link. It's a good read. I know it is suppose to be the upper bound of the relative for floating point arithmetic. But if it was multiplied by a substantial amount (or in some special cases), wouldn't it, at some point, the error can be larger then the upper bound (Epsilon)? Would Mathf.Approximately fix this? (I'm just academically interested at this point, OP should be fine with his use case as one man wouldn't pay that much for drinking.. I think). FYI: https://stackoverflow.com/questions/51019475/what-are-the-possible-usage-scenarios-for-number-epsilon – HardcoreGamer Jul 08 '21 at 03:31
  • @HardcoreGamer honestly I don't fully understand what you mean by `upper bound` but the use case of `Epsilon` is the following: Due to floating point precision something like `5.0f * 0.2f / 10f == 1` might fail since it could actually be `0.99999999` or `1.0000001`. Therefore you rather use e.g. `Mathf.Abs(1 - 5 * 0.2f / 10f) <= float.Epsilon` to check for approximated equality between two numbers. It is **not** for fixing rounding errors in large numbers! There you are absolutely right and if you rely on higher precision you need to use a more precise data type like `double` or `decimal` ;) – derHugo Jul 08 '21 at 15:16

1 Answers1

2

Use ScriptableObjects, as if they were files.

For every type of drink, have a ScriptableObject which you can fill in from Unity easily (even your artist can do this), and then at runtime, you load them into objects of a single DrinkEntity class which loads these values.

This way you don't end up with dozens or hundreds of "DrinkSystemBeer"/"DrinkSystemWhiskey"/etc classes, but you can still keep all your code clean and pattern-friendly.

IMPORTANT: NEVER operate with the ScriptableObjects directly. Simply load them into a DrinkEntity on its constructor. Treat ScriptableObject as if they were xml or json files from which you read your data.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Trickman
  • 56
  • 2