Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Open source Unity games

Discussion in 'General Discussion' started by BobOfTibia, May 30, 2017.

Thread Status:
Not open for further replies.
  1. BobOfTibia

    BobOfTibia

    Joined:
    Aug 24, 2016
    Posts:
    40
    Is there some sort of Directory? Perhaps a list of games perhaps by code they're using?

    Would love to see how people made certain functions with C# or how they set up shaders ETC.
     
    Martin_H, mysticfall and GarBenjamin like this.
  2. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,954
  3. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    On a side note, I really wish there was some sort an equivalent for Github for artists. I know there are some websites where you can download a few free models and textures, but they are not as big or popular as Github for programmers.

    But I think it'd be awesome, if there was sort of a 'de facto' directory for open source art resources, and it becomes a norm for the game industry as a whole, that instead of recreating proprietary art resources every time, they just use some of the AAA quality resources from such an open respository, and also contributing their works to it.

    If indie developers can have access to the same kind of quality art resources that were used in such projects like The Witcher 3, or Far Cry, or big studios can build upon previous works created by other big studios, we'll see significantly better quality games from indies to AAA studios. For, how many hours have to be wasted by game studios everywhere, to recreate very similar looking medieval towns, or some urban cities in varying qualities over and over?

    It might sounds like an impossible dream. But similar thing has already happened for the programmers before. And the big shifts towards the open source movement in the last decades didn't really put professional developers out of their jobs, but instead made their life a lot easier, by allowing them to build something great on top of someone else's work.

    I just hope something similar could happen in future for the art department as well.
     
    Last edited: May 30, 2017
    UnityFan18 and theANMATOR2b like this.
  4. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    mysticfall likes this.
  5. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    I haven't heard about Ludum Dare before, so I better check the place out. Thanks :)

    By the way, I'd rather discourage people from using SourceForge now. I have a few fond memories of doing projects there, but after they started losing their users to Github, they began to do things that have completely destroyed any faith or good wills remaining from the open source community(especially with GIMP project):
     
    matkoniecz and GarBenjamin like this.
  6. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    I wasn't aware of that. I know it seems to have faded in popularity. I actually couldn't remember the name of it as first and had to some searching around to find it again.

    Ludum Dare is a very cool thing really. I have never participated in any of the compos or jams but I often check out the entries.
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    All Unity games for PC are currently open source. In the sense that you can open up the code and have a look at it. I frequently do this when looking for examples of how a particular task was approached.

    Open source in the sense that you can use the code in your own projects is another matter.
     
    NotaNaN and Ryiah like this.
  8. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    It is worth mentioning that some of the more popular opensource licenses cannot be used with unity in unmodified form. GPL, for example.

    I believe releasing source code on Compo is obligatory. However you do not get the right to use the code in your project, if I remember correctly.
     
    Martin_H and GarBenjamin like this.
  9. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Global Game Jam does require your source code to be free for others to use.

    However I'm not sure I would be using Ludum Dare or Global Game Jam as good examples of code to learn from. Each time I participate the product is hacked together for speed over sanity.
     
    matkoniecz, Martin_H and GarBenjamin like this.
  10. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    This code snippet from that site made me shudder, at least :p

     
    Peter77, GarBenjamin and Kiwasi like this.
  11. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    What?! That is an elegant solution. Very simple and straightforward. An entire level editor and generator system. It's actually very similar to what I am doing only I'm reading data from an image instead of text file.
     
    troyofearth and Martin_H like this.
  12. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    Ah... I wasn't referring to the approach itself, which I agree to be a smart one :)

    What I had in mind was that long series of if-else statements (especially with the repeated makeFloor() call), which is almost always an indicator for a bad quality code (or, as sometimes called, a 'code smell').
     
    Last edited: May 30, 2017
    GarBenjamin likes this.
  13. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Okay yeah it can be refactored and improved. Still I think there is sure to be some useful stuff in those projects. Especially when looking for how to optimize the dev time for Unity. Not using it necessarily "as is" but you know what I mean taking the core concept and improving it.
     
  14. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    Of course, I have no doubt that the site contains lot of helpful contents which people can get hints from.

    I was just referring to the code quality of that particular example, and as @BoredMormon noted, maybe something like that is bound to happen in such an event like a game jam, which of course can be a fun socializing event those who participate, even though it might not be an ideal learning opportunity for how to write quality code for others.
     
    matkoniecz and GarBenjamin like this.
  15. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You're kidding me right? It has the advantage of being the first idea to pop up when considering level generation. And it's really easy to write out. But it's far from code you'd want in a production setting.
     
    matkoniecz and GarBenjamin like this.
  16. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    The code is messy. For example, the dude uses foreach, but declares i/j iterator variables, uses if/else, when there's switch/case (and maps of delegates), makeFloor appears in every statement, meaning it can be moved outside of if/else tree, etc....

    Basically, while this example is clear enough and readable, it was obviously written in a hurry. Wouldn't call it a bad code, though, just a messy one.
     
  17. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    I'm curious to see your fancypants solution for it. Personally I like that it's code where I can see at a glance what it does. I personally prefer switch over dozens of if/else, but of the top of my head I'm not sure if you can switch from a char. And the makeFloor thing @neginfinity mentioned... But otherwise, I've encountered things in commercial assetstore products that I found way worse (like having function parameters in an api that don't actually do anything).
     
    theANMATOR2b and GarBenjamin like this.
  18. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    Personally, I prefer using such a code like below, instead of a long series of if-else or case statements (I'm still learning C#, so the loop statements might be further improved):

    Code (CSharp):
    1.  
    2. var tiles = new Dictionary<char, ITileDefinition>
    3. {
    4.     {'*', new FrogTile()},
    5.     {'1', new WallTile()},
    6.     {'g', new GunTile(90)},
    7.     {'G', new GunTile(270)}
    8. };
    9.  
    10. new MapGenerator(tiles).Generate("map.txt");
    11.  
    12. //...
    13.  
    14. public class MapGenerator
    15. {
    16.     public readonly Dictionary<char, ITileDefinition> Generators;
    17.  
    18.     public MapGenerator(Dictionary<char, ITileDefinition> generators)
    19.     {
    20.         Generators = generators;
    21.     }
    22.  
    23.     public void Generate(string filePath)
    24.     {
    25.         var y = 0;
    26.  
    27.         using (var reader = File.OpenText(filePath))
    28.         {
    29.             string line;
    30.  
    31.             while ((line = reader.ReadLine()) != null)
    32.             {
    33.                 var x = 0;
    34.  
    35.                 foreach (var symbol in line.ToCharArray())
    36.                 {
    37.                     Generators[symbol].CreateTile(x++, y);
    38.                 }
    39.             }
    40.  
    41.             y++;
    42.         }
    43.     }
    44. }
    45.  
    46. public interface ITileDefinition
    47. {
    48.     void CreateTile(int x, int y);
    49. }
    50.  
    51. public abstract class FloorTile : ITileDefinition
    52. {
    53.     public virtual void CreateTile(int x, int y)
    54.     {
    55.         // Do whatever it takes to create a floor (i.e. makeFloor);
    56.     }
    57. }
    58.  
    59. public class GunTile : FloorTile
    60. {
    61.     public int Angle { get; }
    62.  
    63.     public GunTile(int angle)
    64.     {
    65.         Angle = angle;
    66.     }
    67.  
    68.     public override void CreateTile(int x, int y)
    69.     {
    70.         base.CreateTile(x, y);
    71.         // Create a gun with the specified angle (i.e. makeGun);
    72.     }
    73. }
    74.  
    75. public class FrogTile : FloorTile
    76. {
    77.     public override void CreateTile(int x, int y)
    78.     {
    79.         base.CreateTile(x, y);
    80.         // Do whatever it takes to create a frog (i.e. makeFrog);
    81.     }
    82. }
    83.  
    84. public class WallTile : FloorTile
    85. {
    86.     public override void CreateTile(int x, int y)
    87.     {
    88.         base.CreateTile(x, y);
    89.         // Do whatever it takes to create a wall (i.e. makeWall);
    90.     }
    91. }
    92.  
    One might argue that it's even verbose than the original code, but as is widely understood, the readability or maintainability of a codebase does not entirely depends on number of lines it contains.

    The more important thing to consider, in most cases, is to make the intention of a program clear, which often can be achieved by introducing new types (after all, OOP is all about types) or new methods. And it's also better to make your code extendable (like adding new tile types) without having to modify the source code.

    I suppose, it's probably worthwhile to mention that, it is considered a best practice to write your code that it can be understood clearly by looking at its API documentation.

    And since the API deals with type hierarchies and type members instead of individual statements, it is better to define each responsibilities/roles/requirements as separate, but coherent types or methods, rather than to put them all in a single method with gigantic if-else statements.
     
    Last edited: May 30, 2017
    Martin_H and Socrates like this.
  19. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I'd probably use a texture instead of a text file. I'd use a couple of for loops instead of for each. I would Instantiate prefabs instead of a method for creating each type of tile. I would use some sort of collection to hold all of the prefabs, making the system extendable.

    The code example is difficult to maintain or extend, is prone to human error, requires the use of a text editor to generate the levels, and is considerably longer then it needs to be.

    The code written is the perfect solution if you need to write code fast, you need to write it once, and you are going to abandon it after a few days. But for anything else, there are better solutions.
     
    NotaNaN, matkoniecz, AlexWei and 3 others like this.
  20. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    You can find lots of good examples on GitHub, ggj like people mentioned but I know when I participated in the GGJ last i was too rush to make anything but hacks and S***ty code
     
  21. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,954
    Welcome to game jams where you are often working on very little sleep and any end result is often best described as a prototype rather than a complete game. I'm betting most of us would create code of a similar nature while under those conditions. Though some of them are definitely worse than others.
     
    Socrates likes this.
  22. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    Yeah, I participated a couple of 'code jam' events in the past, even though they weren't about creating games, so I know how they are usually like

    Honestly, though, I don't really think that chaining if-else statements that long has as much to do with lack of time as lack of familiarity with, or understanding of OOP principles.

    But I understand people tend to produce much less quality code in such events, in general. It's just that I found that particular code snippet to be exceptionally messy, so not really suitable as a learning material for new programmers.
     
    Last edited: May 30, 2017
  23. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    Thanks a lot for illustrating your approach! When I started working in Unity I would not have been able to fully grasp what your code is doing, the disputed example from the jam I would have been able to understand. I fully agree on the "make intentions clear" part, but creating more types than absolutely necessary usually does the opposite for me, because with custom types I don't know what they do and with low-level data types that have meaningful names, I find it easier to understand (or guess) how things work.


    Without proper usecase parameters it can't be determined which of the two is better suited.

    How is that a bad thing? If anything I'd say it's a plus, because it's a massively accessible tool, and text files can easily be used with git.

    Just out of curiosity, when you say OOP, do you use inheritance a lot? I mean obviously I have plenty of custom classes in my current project, but iirc I haven't used inheritance yet. I just never feel like it would help me. Interfaces can be very useful though, I've used a few of those. Maybe I just don't have a good usecase for it but others do?
     
  24. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    As opposed to an image editor?

    The main downside is scalability. Try draw a big level in a text editor, then try draw the same level in an image editor. You'll find the image editor to be vastly superior.
     
  25. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    The important aspect of designing in terms of types, which I think to be the key concept in OOP, is that one should not need to look into the source code itself to understand what each types do, or how to use them.

    For instance, in the original code, one needs to read the if-else statement chains, line by line to understand what it's supposed to do. On the other hand, if you introduce types, you can read the code in a more abstract, or conceptual manner, like:
    • We have some different types of tiles, which we will call ITileDefinition.
    • Each tile definition will create an actual tile in a map, when given a (x, y) coordinate, so we define CreateTile(x, y) behavior in ITileDefinition type.
    • MapGenerator will generate a game map, as its name suggests, based on arbitrary tile definitions, or ITileDefinitions.
    • There will be such tiles that create a floor, which we will call FloorTile.
    • There will be other tiles that create a floor and put additional objects upon it, so we will define bunch of classes derived from the above mentioned FloorTile, such as FrogTile, GunTile, and so on.
    All of these information can be understood by looking at the type hierarchy, and inspect the signature of each types. The biggest advantage of such an approach is that now you don't have to read the actual source code, because it's not hard to see 'FrogTile' will generate a frog object on a floor, for example, because it's easily inferred from its name, as well as from the fact that it's also a subclass of FloorTile (thus, it will create a floor), and ITileDefinition(so that it will create a tile at a designated coordinate).

    And as you can see, the above list reads much closer to what it could be the actual requirements of the game we want to create.

    I agree with you, that for those who are not accustome to OOP, the original code with if-else chains might look more readable than my code. But I suppose it's the same thing to say it's easier to understand if one don't use Prefabs but just create each objects as needed.

    Like such a project without any Prefabs, it will quickly become difficult to manage or understand as it grows in its size. It might be easier to read the actual source code if it's just a few hundreds lines, but it's a lot easier to read and extend by working with a larger, more abstract units like types, if it becomes more complex.

    Yes, I find inheritance to be an invaluable asset to express such a concept like 'a tile that creates a floor and put a frog on it', when we already have the other concept that 'a tile that creates a floor', in the above example.

    OOP is in essence, a specific approach with which we model real world concepts and abstract or generalize them. So, rather than understanding everything as discrete functionalities, like for example such a 'function' with bunch of parameters like 'makeTile(type = "frog", createFloor = true)' for example, it chooses to see the world as a coherent set of interdependent 'concepts', or types.

    And if we are to model the world in terms of such concepts, we inevitably hierarchize them according to how general or specific they are, like 'just a tile' > 'a tile which has a floor' > 'a tile which has a floor and an object on it' > 'a tile which has a floor with a frog on it', and etc.

    That being said, I agree that sometimes it's better to use composition (or a component model, which is somewhat similar to what we usually do with Unity) over inheritance, as it's more flexible, especially considering the fact that C# doesn't support multiple inheritance or mixins, like some other more expressive languages do.

    But I believe there could be plenty other cases where such a simple inheritance will make the design more intuitive, like one we've discussing with the map generator example. So, I guess it's just a matter of getting accustomed to the OOP's way of thinking to see the benefits of using inheritance, instead of writing 'functions' with a lot of parameters to deal with different use cases.
     
    Last edited: May 30, 2017
    Socrates likes this.
  26. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    I was very tempted to criticize the approach yesterday.

    Basically, few issues(opinion):
    1. No support for unity serialization systems. Hot reloading is very useful. However, unity serialization system(which makes hot reloading work) does not support dictionaries, polymorphism, and does not resolve references to anything that is not derived from component, monobehavior or scriptableobject (that includes nulls).
    2. Having class hierarchies is not necessarily a good thing.
    3. A lot of stuff goes against yagni/kiss. If class is empty, (and is not used as a filter in unity), it serves no purpose.
    4. Readability is not improved compared to original switch/case examples.

    Some of the cleanest code I saw was written in procedural style, or with bunch of methods that statically manipulated data structures made without inheritance. Examples include libsdl code, and code from maya (back when I was working on it they made a point to separate methods from data). With OOP there's also always a danger of fooling yourself into thinking that you're doing something useful while in reality you're wasting time moving lines back and forth for aesthetic reasons.

    Also... you mentioned that you're just learning C#. My recommendation would be to grab source code for unity event system, take a look at it... and then never do what they did. Event system is pretty much a prime example of OOP approach going wrong.

    Another interesting thing to check out is Linq which can produce a very concise/expressive statements, but alas, a lot of those generate garbage.
     
    troyofearth and Martin_H like this.
  27. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    The code I wrote is just an example, and only a minor modification of the original snippet which is also very far from being production ready quality.

    The same idea and structure can be easily adopted if you choose to swap the dictionary instance with an editor injected array of components or prefabs on which ITileDefinition derived classes are attached, which will have no such problem with serialization, for example.

    (By the way, I don't think the code as it is would suffer from any serialization issues even as it is, because those tile definitions are by design, stateless. Please correct me if I'm wrong.)

    And as to the problem with MonoBehaviour or ScriptableObject, that's the reason why I really hate the usual Unity's approach, but fortunately, I found that using a DI container like Zenject can mitigate that specific problem a great deal.

    In my opinion, 'KISS' principle should not be applied to such cases like marker interfaces, for example. And in my example, those classes that derive from ITileDefition might look empty, only because I omitted actual frog/wall/tile creating code, which weren't included in the original snippet as well.

    And as to readability, I can repeat what I wrote above, that it depends on each person's experiences and the scope of a project. You can't really expect to understand any big software project, like Spring Framework, for example by reading its source code, as it would take months or even years to complete.

    But if you are familiar with the basic principles and patterns that the authors of that framework themselves used while they design such a project, it can be done much easier by just reading the API documentation instead of the actual source code. OOP was invented to solve such kind of a problem, after all.

    I'm using both LINQ and also Rx already, by the way, though I couldn't think of a proper way to handle that file reading part in LINQ, when I wrote that example (I'd appreciate if someone could show me the way :)).

    I found them to be very useful, but as I'm moving from Scala background, I can't help but thinking that it was much easier back then, with all those builtin functional programming tools.

    By the way, I agree with you that it's entirely possible to write a clean, manageable code in procedural style.

    It's just that with OOP, you have some common convention and conceptual tools(i.e. design patterns) to organize, or structure your code, so it becomes easier to read or work with other people's code, provided you are already familiar with such shared concepts.
     
    Last edited: May 31, 2017
  28. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    That's a good example where I just don't "get it" why anyone would want to make a class for each tile. I would have one class Tile, and it would have public variables for everything that can be specific about a tile, like its floor type, the object on it, its color, height, etc.. Abstracting the data away into classes would make it harder for me to deal with it, in every way that I can think of. I see no benefit here to split that into multiple classes (except the frog, he can get his own class if he's supposed to do something that goes beyond what something like tile.frogCount could represent).

    But I'm certainly not adept at using OOP best practices because I mostly avoid it in general. This might at least in part be a me-problem that I just don't see the appeal. I certainly don't want you to change the way you'd handle it, if it works well for you!
     
  29. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    All classes mentioned in the example will be nulled upon reload. If anything holds a reference ot them, you'll get flurry of null reference exceptions immediately afterwards. It is unclear where the "map" in your example is stored, so that one may die as well.

    There's also an option to figure out how serialization works.

    The kiss principle is closest to the universally useful rule I know. Haven't encountered a situation when it was a bad choice.

    The biggest issue (for me) in your example is:
    Why use a class when you can use a lambda function?
    That would be one of the first choices for dictionary-based factory.
    Original code generation is quite uniform, and would be best reduced to delegate void (int, int);
    Classes (imo) are for situations when something needs to persist or functionality should be exposed to other files. In this example, there doesn't seem to be a need for that, so no need for classes. Anyway.


    Over time I found that it is apparently the best idea not to overinvest into class hierarchies, and reliance on class hierarchy reliably proved to be a time waster in most scenarios.

    Either way, it would seem that we're in disagreement. So, I think it might be the best idea to just drop the subject.
     
    Martin_H likes this.
  30. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    I'm still a beginner in Unity so I'd be grateful if someone would point out any misconceptions that I might have. And, as what you said above doesn't match what I understand to be how serialization works in Unity, I hope you can point out where I'm wrong.

    It's my understanding that instances of a custom class which is assigned to a property of MonoBehavior won't get nulled as you said, provided they come up with [Serializable] attribute.

    Instead, if I'm not mistaken, it will simply be recreated as a new instance of the given type, unless it derives from another MonoBehavior, so breaking referential identity after a reload. But it won't be a problem in this case, as all such classes are essentially stateless, that is without any references to other live instances.

    Probably the more serious problem might be the fact that Unity doesn't take polymorphism into account when it serializes a collection of sub classes, like a dictionary of ITileDefinition, in this case.

    But as I said already, it can be easily solved by using a component/prefab instead, or better, a proper DI framework which will solve such a problem with referencing dependencies with full support for polymorphism.

    I won't argue other points about usefulness of OOP in general, or as to why I used classes instead of delegates, if you don't want to continue the discussion though.
     
    Last edited: May 31, 2017
  31. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    https://docs.unity3d.com/Manual/script-Serialization.html

    It is well explained here.

    Quick overview:

    Basically, generic classes do not serialzie even when marked with Serializable attribute, unless you derive non-generic class for them. A common thing is:
    Code (csharp):
    1.  
    2. [System.Serializable]
    3. public class IntMap: SerialDictionary<int, int>{
    4. }
    5.  
    Where SerialDictionary in turn inherits Dictionary and supports ISerializationCallbackReceiver. This one will serialize. Your map, however, will not.

    In case public variable has a provided initializer "= something()" it'll be recreated according to that consturctor, but without that you may get a null isntead.
    Nulls are not supported, polymorphism is not supported (see article), Animal animal = new Cat() will not deserialize a Cat() upon reload, but istead will fall back to Animal().

    Also, upon serialization/deserialization, following order of function calls still apply:
    https://docs.unity3d.com/Manual/ExecutionOrder.html

    In case of active script being reserialized (which happens several times per second in unity), process goes like this:
    OnDisable() -> Serialize -> Deserialize -> Start() -> OnEnable()
    Meaning, if you want to babysit some sort of non-serializable object (for example a child gameobject with HideAndDontSave flag in an [ExecuteInEditModeScript]), proper approach to create the object within OnEnable() and kill within in OnDisable(), and it'll be available every time an object is visible and active. That's how components that render text and draw dynamic meshes work in unity -> including that level editor mentioned in other thread.

    In case you need a serializable delegate, unityevent is the way to go, because this one serialzes.

    That's the rough idea of it.
     
  32. iamthwee

    iamthwee

    Joined:
    Nov 27, 2015
    Posts:
    2,149
    When Rob Pike invented golang he dropped all OOP concepts, I believe some sorta rudimentary struct is all it has.

    Haha, there's goes OOP!
     
  33. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    @neginfinity I believe that we were essentially talking about the same limitations here. It seems that when you said 'all classes will get nulled', you were referring to the contents of the dictionary, while I understood it to mean any properties with type of ITileDefinition derivates.

    Anyway, it is true that we cannot simply serialize the dictionary itself by default, but it's also what I mentioned myself above, with two possible ways to workaround the problem (one with components, the other with a DI framework).

    Even the original example with if-else statements will need to introduce a very similar approach, if it aims to be extendable (i.e. introducing new tile type without modifying the source), so I don't believe it to be quite fair if it is to be considered a defect inherent with OOP approach.
     
  34. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    GunTile, for example requires 'angle' property which is not used by any other tile types. So it might become difficult to trace which variable is used for what, if we keep putting every such variables into a single Tile class.

    And more importantly, such a design won't allow introducing a new tile type or customizing an existing tile without modifying the source code, both of which can be easily handled with an OOP version.

    But I agree that not everyone has to adopt OOP, or over engineering everything despite of actual requirements. It's just that I'm saying OOP approach can have very real benefit for certain projects, especially for those ones with larger scope and complex requirements, and once you get familiar with the concepts, it can be actually easier to read and write code following that principle, despite of potentially increased code size.
     
    Martin_H likes this.
  35. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    And that's what KISS principle is for.
    By default there is no need to make a program extensible.
    Unless such feature is requested in program spec, it is not needed, and therefore working on implementing proper plugin framework (because extending without modifying source means plugin framework) will be a wasted development time that could be spent on something else. Meaning, that trying to do things in proper extensible fashion is unnecessary effort which will add ongoing maintenance cost on top of that (because extensibility is expensive).

    Basically, the reason why I adhere to KISS/YAGNI principles and Murphy's law, because I think that it is not programmer's job to make beautiful/elegant/wellstructured code with logical class hierarchies.

    Instead, I think that programmer's job is to implement a feature request in minimum amount of time and at minimum development cost (preferably for maximum cash payment, by the way), where development cost includes both immediate cost (how many hours you wasted right now), and future maintenance cost (how code maintainers will try to find and kill the original programmer. Erm. I mean, how many hours will be wasted maintaining the code).

    KISS works amazing when you keep development cost metric in mind. OOP does not. That's mostly because KISS allows you to use any tool including OOP, while OOP alone is only one approach out of many.
     
  36. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    I'd like to argue that requirements tend to shift all the time in real projects, and that's why people have been trying hard to find a way to write a software that can adapt to such changes with a minimal impact(and the same goes for methodologies, i.e. Agile).

    If we interpret KISS principle to mean that we should not care for any such flexibility, we might as well tell people to just duplicate game objects whenever it's needed without bothering to learn how to use Prefabs, unless they begin with specific requirements of expecting large number of similar objects from the start.

    And like creating a Prefab is not such a hassle, compared to potential headache that can happen later, if you just kept duplicating objects, introducing a factory, or class hierarchy is not such a big deal for a programmer who is already familiar with the basic principles of OOP.

    Prefabs might look equally confusing to those who are just beginning to use Unity, as a factory class might look for a programmer who's never coded in OOP. And just as Prefab is part of the core concepts of Unity platform, such a concept like inheritance is also an essential part of C# language, which is, of course, an integral part of developing games in Unity.

    But again, I'm not saying OOP is some sort of a silver bullet that every one needs to follow. However, it's also true that it's one of the most popular, and well understood programming principles for now, and it wouldn't have become so widely adopted if it didn't bring any benefits for an average developer.
     
    Last edited: May 31, 2017
  37. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    The point of using KISS/YAGNI is to minimize impact of future changes by not digging yourself into a hole because of some incorrect assumptions about feature or functionality that was not part of the spec.

    Nope. Because duplication increases future maintenance cost.

    Also, it is not just KISS, but also YAGNI principle, which, if I remember correctly was part of the ideas used in extreme programming practices which then turned into agile which then turned into something so horrible that even avan original designers said that Agile is dead.

    The overall idea is to minimize development cost, which actually goes in hand with "adapt to changes with minimal impact". The problem is that starting with class hiearachy right off the bat goes against your own idea of "adapt to changes with minimal impact". That's because when you start implementing class hierarchy for something that wasn't explicitly requested you already impose limitation upon yourself and create something that you will have to modify later. So, in this case with good intentions of making software extensible (even though that wasn't requested), you work towards increasing impact of future changes. If you DON'T create the class until it is absolutely necessary, then you won't need to modify it later.

    ....

    The whole set of ideas is rather elegant in my opinion, makes a lot of sense, and to end up with this kind of approach, I had to do many many costly mistakes in the pass. So, I'd advise to think it over.

    Anyway, that's enough methodology talk.
     
  38. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    It's good for you that you have arrived at such a methodology that works for you. Honestly, I find it rather strange that you seem to think class hierarchies are something evil, when C#, with all its tutorials, tools, frameworks, and etc are built around the assumption that they are the fundamental building blocks of any software system which is written in that language.

    Personally, I don't usually feel much difficulty in refactor class hierarchies to adopt to new requirements, or find it any easier to do the same thing, without them. In fact, I can't see how I can even create a big system in such languages like C#, if I should not begin with some abstract type hierarchies.

    But again, I don't have an intention to argue that you should change your way if it works for you.

    I just want to expect the same from you, as OOP way of thing has been working more or less fine for me, for the past 17 or 18 years. So, I'm pretty much accustomed to it by now.

    We can, of course discuss relative advantages or disadvantages of each approaches. But as you said, it seems that we a quite different views on how to write a software so it might not be easy to reach an agreement.
     
    Last edited: May 31, 2017
    Martin_H and neginfinity like this.
  39. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    My original primary programming language was C++ and not C#. Sadly, Unity does not provide C++ bindings, and I miss certain C++ features daily. C# by itself is not a very convincing example of a successful OOP design, and its hierarchy design is very awkward. My personal pet peeve is Array and List<> not supporting common "Count" or size() property, plus there are minor things like forgotten interfaces akin to ICloneable. Basiaclly... one really interesting things that look very promising long term in C# are quasi-functional interfaces along the lines of linq, and the whole idea of extension methods. This is a feature that seems to have some serious long-term possibilities, and I think it is going to be borrowed by C++ at some point.

    My attitude towards OOP is based on personal experience of working with OOP. In my experience, OOP is usually overused, and people stick it everywhere without a need. That's why "object hierarchies are evil". They fall into "amazing problem(tm)" category. ("Amazing problem" is a type of programming task that can be incredibly interesting to work with, but at the same time has potential to waste infinite number of development hours while actually doing nothing useful). Meaning it is most of the time a distraction.

    In practice it means that I'll go with simplest currently necessary solution and then refactor it as it grows in complexity, moving away shared portions of code into other functions or classes, should they become necessary.Classes can be later split into hierarchies, should need for polymorphism arise. The overall idea is to keep sanity of the codebase at all stages, keep manageable changes, and avoid doing actions that potentially will backfire in the future.


    Yup. Also, reaching agreement is not really necessary, keeping separate views works as well.
    ----------

    By the way, wasn't the thread originally about something completely different?
     
    Martin_H and mysticfall like this.
  40. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    Not to continue the discussion, but I'd like to mention that I strongly agree with you on this point. Not that I'm any expert in theoretical aspects of language design, but I don't think C# to be an ideal language for OOP either, and the only reason that I chose to learn C# was because of Unity.

    It feels more or less like a polished version of Java (which it should be, considering its history), rather than something more modern like Kotlin or Scala.

    I just noticed :D
     
    Last edited: May 31, 2017
    Martin_H likes this.
  41. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    https://opengameart.org/

    Honestly, I cannot see AAA companies sharing their art, for free or pay. What is in it for them? And if I were an artist whose art suddenly ended up open source I would probably not be happy. I wouldn't want my art ending up in some kid's game on Steam that gets negative reviews.

    Imagine if you were a painter and prints of your picture were suddenly out there for free, without your permission? What if people could claim them as theirs, no credit, no royalties.

    Yeah, it would be nice to be able to get free AAA art, but it will probably not happen unless a game fails like Ryzom (not AAA today, but was once upon a time).

    Probably the biggest issue for a game developer and free AAA art is that it would come from so many different sources that matching it would be horrendous. The game would look like it was patched together. :) I am sure the term "asset flipping" would take on new meaning! :p
     
  42. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    Of course, I don't mean that artists should work for free :) Actually, it was quite a similar situation before the open source began to be widely accepted among software companies. Before that time, companies and even some professional developers tended to be much hostile to the movement, seeing it as a potential threat to their income.

    Things have changed once people began to see that they can actually make more money out of such open source projects, because they can build a new product much faster starting from a solid ground which is already available for free, or create new type of business models, like education or tech support, and etc.

    It just an expression of such hope that something similar might happen in gaming art department in future. Like professional developers today, artists won't lose their jobs when quality open sourced art resources become a norm. Rather, they maybe able to create more impressive things, regardless of whether they are belonged to a big studio or a solo artist. I guess if a artist could create a high quality medieval house in a week, he or she might do the whole town in the same amount of time, if all the source materials are already available for free. And companies still need to hire such types of artists to provide them consistent art resources and direct the art style.

    By the way, thanks for the website. It looks to be very useful to me :)
     
    UnityFan18 and Teila like this.
  43. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    There are some gems on that website. I have actually gotten ideas for my own artwork sometimes from things I have seen there. Great for prototyping.
     
    mysticfall likes this.
  44. goat

    goat

    Joined:
    Aug 24, 2009
    Posts:
    5,182
    There is more than just GitHub out there.

    What's wrong with shareCG? Or the multitude of Blender sites like BlendSwap? And there many free textures sites, free fonts, free clip art and so on.
     
  45. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    Not all of these are free to use in commercial games. Read carefully!
     
    Martin_H likes this.
  46. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    I only dabbled in 3D modelling myself, but I found that the site you mentioned to be really helpful for me (especially the latter, as they provides Blender projects themselves, so I can learn how something can be done).

    But I still feel that it isn't such a norm like it is in the development field. For example, my typical commercial Java or Scala project would involve using something like 3-40 libraries (excluding transitive dependencies) which are all open source.

    And if I choose, I can develop them entirely with open source development tools, and deploy them on open source application server with open source database on an open source operating system.

    And it's not just for small projects like smart phone apps, but also for enterprise systems that big companies use. And it's not something unusual that only poor development studios do, but almost an industry standard.

    Before open source became such a norm, it was much more difficult to create something big because they had to build all such 30-40 libraries themselves if such functionalities are needed. Now they can just use them for free and spend their time in doing something more valuable for the customers.

    And back then, they had to rely much on custom frameworks or libraries that other developers created before them who work for the same company, and use some specific commercial products that company happened to purchase.

    As such, small companies didn't have much chance to compete with big ones, and when developers move to another company, they often had to reeducate themselves with other custom frameworks and other proprietary products.

    And I guess it's basically how it is with the game industry right now, regarding art assets - big studios employ many top class artists to create their own art repository, while another big company doing the basically the same thing only for themselves, and indie and solo developers have to rely on much lower quality assets which they can grab on a few free sites or buy relatively cheaply.

    If it was really the same with how it is currently in the development field, even a solo developer would have access to the same quality art repository as those who work for AAA studios do, and he or she can use almost every art materials that can be used to create AAA games for free. (And probably, even such tools like Substance or Unity itself would be the same as well, or at least there would be a free, open sourced alternative for them which provide complete compatibility with such commercial tools.)

    This might sound like a crazy propaganda from someone who advocates software piracy or anti-capitalism, but it's basically what happened during the last two or so decades in software industry. At first, companies like Microsoft tried to kill open source, but when it became too big to do so, they had to embrace it, so now they act like they were the biggest patrons of the movement.

    Actually, Unity itself was benefited directly by such changes, since it relies on Mono for everything related to C#, which is an open source implementation of .NET platform, one of the key products of Microsoft.
     
    Last edited: Jun 2, 2017
    UnityFan18 and Socrates like this.
  47. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    Quality of content vary wildly, not all of it is suitable for your games, plus there are multiple licensing gotchas. CC-BY, CC-SA, CC-ND, CC0.

    My "favorite" licensing caveat is makehuman model export. Basically, modeling export is CC0, BUT only if it is done using official distribution. However, best quality models are produced via mhx2 exchange format, BUT after certain makehuman versiion it is no longer part of original distro. Meaning that if you export model via MHX2 under most recent version, it is now GPL and you can't use it in your game. Plus there's insane statement on the site where they say that using CC0 somehow can result in creating GPLed derivative work.

    Bastioni Lab in blender is better in that regard, because 3d content is merely CC-BY (would've prefer it to be CC0, though). and it is produced right inside blender, meaning exporting/manipulating it is no longer an issue.

    The whole character generation thing is quite depressing and it would be great if someone raised, say, few millions, and used them to fund development ofr CC0 morphs for an equivalent of makehuman, jsut so people wouldn't need to deal with all that nonsense.

    The one thing I'd really love to be able to use is movie-like object library. I've been looking into "before/after cg" videos recentely, and one of them displayed a HUGE library of objects - cars, street signs, pretty much everything you could ever possibly want. This would be cool to have access to.

    But getting back to blendswap... resources of this kind usually host unusable content. I can't remember even one time where I managed a find usable model online on any resource like that.
     
    mysticfall likes this.
  48. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    I can't agree with it more!

    I got curious, so checked today how large open source library repositories are. It seems that NPM, such a repository for Javascript language hosts 461k modules as of today, with 50+ new items added on daily basis. And there are many similar repositories for other languages, like Maven for JVM languages, which hosts 188k libraries with more than a few million files.

    According to an article published couple of years ago, NPM recorded 1.5 billion downloads in a single month. It's just mind boggling to see how big it became.

    Unity's Asset Store is super helpful even as it is. But for now, it 'only' contains 3k free items in varying quality, and they are not entirely art assets either.

    Just imagine how much easier it will become for game developers, if that number gets 100 times bigger, including many AAA quality assets.

    I'm not saying that something like this can happen in a few years, but considering how it became a reality in another field, I suppose we can regard it as something we can aim for in the long run, at least.
     
    UnityFan18 likes this.
  49. mysticfall

    mysticfall

    Joined:
    Aug 9, 2016
    Posts:
    649
    By the way, I followed the same route from MakeHuman to Manuel Bastioni, when I researched viable options for character generation feature for my game, and was frustrated pretty much the same.

    As you said, Bastioni Lab allows its users to use characters generated with the product under a very permissive license. However, it is explicitly forbidden to use the source data or code used to apply morphs, which means it's essentially useless for such games that provide a character customization feature.

    I had a few words with the author of Bastioni Lab about this issue, asking him if he'd be willing to change the license of his product so it can be used in games, but it seems that he's not really interested in such a usage.

    So, I found that UMA is the only real option at the moment, if you intend to write an open source game with a character customization feature. There's even an attempt to create a custom UMA 'race' out of the base model of Bastioni Lab, but even though it looks promising, I'm not too sure if it will get much support in compatible clothings or hairs, and etc.

    I wish something similar with Text Mesh Pro could happen to UMA in future, so we can have a commercial quality character generation feature out of the box. But I gues that it might make MCS people angry, and UMA probably needs another few years to mature and get more traction before it can be seriously considered for such an option.
     
    Last edited: Jun 2, 2017
  50. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,554
    I did make a video about creating custom race in UMA once. Not sure if techniques from it still apply, though.

    In case of Bastioni Lab/Makehuman the idea usually is to generate base meshes, and then assemble alterations yourself, because in-game character customization might need a very different set of parameters.Number of parameters in Bastioni is very large, while in makehumsn customization of certain features is very limited. If I remember correctly, makehuman barely has any support for adjusting facial features, while in bastioni face customization interface is confusing.

    In the end I think it would be great if some sort of big company took development of opensour.... actually development of CC0 assets under their wing and funded it. For the greater good or something.
     
Thread Status:
Not open for further replies.