3 ms·
As a semi-retired professional gamedev, I don't get this. Let me qualify what follows by saying that I currently program quite a bit in Clojure and ClojureScrip
by optionalparens 10y ago
As a semi-retired professional gamedev, I don't get this. Let me qualify what follows by saying that I currently program quite a bit in Clojure and ClojureScript on my personal/side project, and I love both languages. Additionally, Lisp was one of my first languages several decades ago. Sorry for the length.
Game programming like most programming largely requires choosing the right tools for the job. While I agree it is important to factor in the skills that you team has, the choice of Clojure + Unity + this write-up seems like retro-fitting for the wrong reasons. Regarding Clojure, I can appreciate what Arcadia is trying to do, but it seems like an odd choice for an unskilled game dev for anything but messing around/intellectual fun at this point. This is both because the software is quite honest and labels itself alpha, and because Clojure and Unity is not necessarily the best combination IMO for many reasons. The primary reason I'd contend this is because it is a huge pile of abstractions of abstractions with not enough payoff. Even just browsing Arcadia's source, I can also already see a few bits of code that aren't optimized as well as they could/should be for something like this. I can only hope the article author is not serious about pursuing a commercial quality game of significant complexity and power with this approach (i.e. not necessarily AAA level, but upper-tier indie).
As for functional programming in games, it is a big subject and an interesting one, not to mention a worthy pursuit. Indeed, huge amounts of the trends in game programming for the past two decades at least have been moving to functional paradigms. Entity systems are a great example of this. One way to think about Entity Systems in particular in relation to a functional language like Clojure is that it essentially allows you to think about your game state as a reduction of states (entities with attached components and systems operating on them) over time. Furthermore, as multi-core programming becomes more important, some of the constructs that make concurrent programming, or even parallel programming easier are commonly found in highly functional languages. Clojure is no exception and has many things are amazing to this end, but not all are necessarily useful in the context of a non-trivial game. There are many more things I could touch on, but suffice to say that programmers are bending over backwards to make C and C++ in particular, followed by C#, Java, Swift, and other languages behave like functional language. Ironically, I think part of the problem with most functional languages is that people are pulled from the other end and forced to make these languages behave like C++ to get acceptable performance and other traits.
Despite many OO/imperative languages used in game dev moving towards more functional trends, the promises, power, and tools that most of these languages provide are vital. There are too many reasons to list (some good, some bad) why C and C++ are still dominant in this world for serious game dev work, but a few include existing tooling, full control of memory, ability to work around language induced performance roadblocks, possibility of portability, optimization per platform if required, bountiful workforce, and low-level integration points with hardware, SDKs, and tools. That's not to say other languages don't have these things, but rather they have some critical flaws in some of these areas that make life harder than it needs to be at the cost of actually getting a game completed, which in the end is one of the most important things.
I know it's frowned upon, but I'm splitting this rather large comment into two parts.
- optionalparens 10y agoClojure suffers some because of the reality of today's game dev ecosystem. Just looking at the source of some past attempts to wrap things like LWJGL or OpenGL (hint, none of these tend to look like Clojure anymore) should be enough to answer some of the questions why this is. There are many others reasons as well that only come to bite some people until they are in the middle of a project. Beyond those reasons, even just dealing the JVM or the CLR for a game present significant challenges to a developer. Unity itself has had to work around challenges too, and the abstractions and development comforts it provides are not free. Even experienced Unity developers who use C# still have to be mindful of how they write their C# (i.e. don't write the prettiest code even if you can because it will punish you). Of course this is true of any language and for other platforms like in mobile game dev. The point is that it's especially limiting to have additional layers of abstraction largely beyond your control. Eventually, it reaches a critical mass where you're writing this weird meta-language to do what you want because writing a game with the ecosystem around you forces that instead of letting you write idiomatic code in the language you picked. The further you get away from the metal for a game, no matter how simple, the more you will face problems. It's nice to use languages like Clojure, Python, Ruby, JavaScript and so on for games, but for serious work they often get in your way. For instance a common problem the average developer encounters is the game loop vs. frame rate - how do I get enough done during a tick to not grind the game to halt? Garbage collection, de/allocations, and so much more become your enemy and you start to feel like you're fighting some kind of magical force trying to slow down your game or make it less predictable, rather than being productive or even optimizing it in sane ways. And yes, predictability is vital to writing a good game, because the last thing a player wants is your game to do stupid things at inopportune moments like in the middle of a jump, never mind other concerns like debugging, multi-player, or platform requirements. Of course there are workarounds for many problems you may face, but as game complexity grows, things tend to scale out of control for most people. Many of these problems cut so much in to the time or make you have other sacrifices that you start to feel like you're largely missing the benefits of working in these alternative abstractions. At some point you just end up breaking all the rules of your language/tools/libraries to get the game to the level you want. Worse, you're working on many problems that are quite far from actually finishing your game. Obviously for simple projects, much of what I've mentioned previously is not a problem, just to again make that clear. Getting back to Clojure, I feel it really suffers from the aforementioned issues for non-toy games. This isn't an indictment of Clojure, just about picking the right tools. Immutability, atoms, refs, agents, CSP, sequences, transducers, recursion, and so much more seem like they would allow making a game quicker, easier, and with less headaches. What ends up happening to most people I've seen who try to use these kinds of tools, whether it is Clojure, Lisp, Haskell, Elixir, or anything else is that at a certain threshold of requirements, is what I mentioned earlier - it all falls apart. At this point, you spend all your time removing all the goodness the language and tools provide. You start writing your own libraries, often down to numbers, matrices, etc. because you have no other choice if you want things to run in a sane, predictable way and to integrate with anything like OpenGL, input libraries, hardware, SDL, and so on. You throw out immutability in huge parts of your game, and you realize that refs, agents, channels, sequences, and more are just making life worse, not better. Pretty soon the entire language is stripped down into something almost unrecognizable, left with only a few core nice things. You then descend into the next layer of hell and start porting things into Java and calling them from there. Even in Java this can happen to a large degree. Add in more unpredictable stuff and abstractions like Unity, Unity plug-ins/add-ons, multi-platform requirements, talking to other libraries you want to use, and so on. The author of the article mentioned simplicity as a selling point, but for non-trivial contexts, you will almost certainly throw simplicity out the door. It starts small and snowballs as I described. For someone building a text adventure or other simple game, you probably don't even need Unity anyway. If you're building a smaller indie game or want to get something done quickly, just use Unity and C#, and you'll get it done quicker and benefit from the ecosystem better. If you can't/won't learn C#, you shouldn't be programming or making games. I know that sounds cruel, but at some point we all need to acknowledge our skills. A game developer should be able to learn any language and be productive in it quickly. The average game dev may not touch the entire game, but more sophisticated games often use several languages, especially if you count things like shaders and scripting engines as being distinct. If you're just learning/new to game dev and/or really want to learn Unity, just use it as intended, otherwise you're adding more layers of abstraction and complications that make it actually harder to learn anything, and worse to get things done. It may often seem like you figured something out and using your favorite tool will get things done quicker, but most of the time you'll hit the ugly thresholds I described when you try to combine it with something more sophisticated like Unity. Use things as they are intended. If you want to make a game in Clojure, great, just keep it simple, write your own minimal engine optimized for Clojure or hope someone makes one someday, or go the ClojureScript route to again make something simple. In summary, Clojure is indeed an awesome language and you can write a game with it, just I wonder what is to gain using it for Unity. In the general sense of things, I wouldn't recommend layering too many abstractions when building games. If you feel otherwise, I'll refer you to the graveyard of projects that have tried to take X and make it work with Y - it is a huge, sad place. That said, I'd love to write a non-trivial game in Clojure or another functional language one day, somehow.