
Choosing Functional Programming for Our Game - swannodette
https://mooistudios.com/2016/12/19/choosing-functional-programming-game/
======
reitzensteinm
I'm a massive fan of Clojure (I spoke at EuroClojure this year), and have used
Unity3D for 5 years... I was also the developer of the first big iOS Haxe
game, another unproven platform at the time, years ago.

I would be very concerned about straying too far from the garden path while
also trying to ship a commercial game.

Unity's GC isn't even generational, a very bad mix with garbage heavy Clojure
code. Expect confusing, bizarre and transient performance and memory use
issues. Debugging will be a nightmare.

And on top of that, Stack Overflow doesn't have an unlimited supply of Clojure
JVM answers; Clojure .Net through IL2CPP? Forget it; you'll have to figure
everything out yourself.

It's generally a mistake to make the initial development more pleasant at the
expense of long term maintainability; and I think that's the trade off on the
table here.

~~~
jackmott
F# with monogame will get you better performance and less weirdness, it is a
pleasant lighter weight environment. unity gc and runtime are rapidly
improving now that ms owns xamarin though.

~~~
psyc
Where did you hear of the GC improving at all? I've heard vague intentions for
years, but never anything concrete.

~~~
jackmott
they have a roadmap with the plans laid out on their website. it was
impossible in the past because xamarin did not want to sell them licenses for
newer mono. now Microsoft owns xamarin, and they are happy to. some
improvements have already landed at least in beta.

~~~
psyc
Unfortunately, although it's on a page named "roadmap", it doesn't look like a
GC upgrade is part of any concrete roadmap. It's in a big bucket labeled
"research".

On topic, I just want to affirm that it's hard to overstate the inadequacy of
Unity's GC, or the amount of time one can sink into optimizing for it.

~~~
mquander
The GC upgrade is going to happen when they upgrade Mono, and the Mono upgrade
is definitely going to happen, although I don't know if it's going to be
before Unity 6. (Source: Unity people have suggested this to me.)

------
spacepluk
Hi there,

I'm one of the programmers at Mooi Studios. We intentionally avoided being
very specific in the article because we were expecting some skepticism :)
Because of this it might sound like we made this decision without putting any
thought into it, and that's not the case at all.

I don't want to argue about what is the best tool for the job, because
honestly I don't think anyone can say something like that and be 100% certain
about it. All I can say is that I've tried those tools before, and I'm pretty
sure I don't want to write software that way anymore.

We are aware of the challenges, and we know that using C# would be easier in
some ways. But enjoying what we do is a big deal for us, and we're willing to
do some extra work to get there.

Ultimately, whether our games succeed or not has little to do with the
technologies we use. I just finished Hyper Light Drifter which is probably one
of my favourite games of all time, and they made that with Game Maker.

Anyways, for now we're only using Clojure to replace C# for game scripting.
We're not writing a full game engine or anything with it (yet, hehe). We
believe the differences in performance for these purposes should be neglible,
and initial testing seems to confirm that. The gains in simplicity and
workflow are real and are huge. And most importantly we're enjoying every
minute of it.

Cheers,

------
seanparsons
I'm not a fan of LISPs, but this is really cool, especially the inbuilt REPL!

Now if I could use Haskell in Unity3D then I'd get hella excited, but there's
a lot more barriers there methinks.

------
everyone
I've been hacking away in as my job Unity for years..

Can someone tell me do they think the practice described in the article is a
good idea? (The writer says they are just learning so their opinion is not
very valuable to me (When theyve cranked out a bunch of games on various
platforms and encountered all kinds of horrible shit and overcome it, it would
be more valuable to me))

I'm all too familiar with OO's many foibles and I'm interested in functional
bur have never done any.

One thing I've heard though, is that OO is bad for most stuff _except_ games.
Where you actually have this world with all these entities composed of various
objects going around in it about their business. Its does make sense to have a
'Cow' object that has state + methods to get it to do various things like
'moo'

Additional: Looked around a bit and the Arcadia repo says.. " Arcadia is
alpha-quality software, and shouldn't be used for anything important yet. "
I'm also try as hard a possible and use as much standard, vanilla Unity stuff
as possible, as the more weird custom plugins and whatnot you use the more
heartache you get when it comes to building and releasing + updates on a
million damn phones or PC setups. Anything not standard has to justify its
existence against very jarsh criteria.

I will download and mess with this though. I'm actually really excited to do
some functional programming!!

~~~
mquander
I've programmed mostly-functional stuff for a while in a bunch of languages
and I have been working on a large performance-intensive (massively
multiplayer, VR, and mobile!) Unity codebase for the past year.

My conclusion is that functional programming is still a good idea to the
extent that you can do it. Specifically, you should still minimize and
encapsulate mutable state, and you should write pure functions when possible.
However, the infrastructure doesn't exist to do functional programming
efficiently in a lot of ways. Examples:

\- Most of the .NET standard library functions over sequences (i.e. LINQ)
incur substantial time overhead and do a lot of heap allocation. Writing and
using generators, same story.

\- Anonymous functions incur heap allocations and overhead which does not seem
to ever be optimized out in Unity's Mono runtime.

\- .NET's standard library data structures are mutable.

\- Most of Unity's API and the libraries people write for it are not
functional.

I don't think you would be wise to try to fight these facts and paper over
everything with functional abstractions, or you will die of a thousand small
performance cuts.

~~~
hacker_9
Just a note, this is mainly an Unity problem as they use an old Mono compiler
and runtime. Additionally lambdas only create garbage when you capture local
variables, and the normal GC is optimised to run without you noticing
collections.

The latest C# also has a whole library dedicated to functional data structures
[1]. Additionally the C# compiler was rewritten in a functional style (proving
it's capability IMO) and is completely immutable. It made sense for their use
case as they can pass the syntax tree around to other threads now without fear
of it changing.

[1]
[https://www.nuget.org/packages/System.Collections.Immutable](https://www.nuget.org/packages/System.Collections.Immutable)

------
jheriko
this isn't a property of functional programming.

a long time ago i used to write code in something called 'AVS' for Winamp...
it also let you modify code at run-time, but it was certainly not functional.

you can actually do the same things with C#... and unity does let you do it
out of the box to some degree. there is no reason why that couldn't be further
developed though.

~~~
optionalparens
Agreed, and I'll add a few things.

You can argue that lots of games can/do modify things while running. Entity
systems allow components to be added at runtime. This not only allows for
different code to be executed, but also I've seen code that reads components
and hot loads additional code for systems supporting those components if
necessary, which can be done a number of ways, and raw from the source even.

Smalltalk also supported this and isn't really functional. In addition to the
Smalltalk environment itself pretty much being a live environment, I saw
things like serializable continuations in Smalltalk. You could do fun things
like a Gemstone Smalltalk app I saw that would take the image state and allow
hot modifications via a bug tracker.

There's tons of other systems for doing this. And it's also a reason why many
games write big chunks of the type code you would want to hot load in
scripting languages like Lua.

There are tons more examples and has no relationship to functional programming
other than to say that it was a common thing in the Lisp world many moons
before most of these other things existed.

------
fatalogic
Whether this they stick with Clojure/FP or not, isn't it important for them to
at least try. Sure maybe FP isn't the best tool for this job right now but
maybe someday it will be. However as a development community if we don't even
try to use it for real projects it will never get better.

Perhaps through their trials and tribulations they will gain the knowledge to
aid in the development of Arcadia/ Clojure + Unity. I just feel like there is
a lot of well meaning but discouraging comments here but I think people often
forget the science part of computer science. Sometimes you just have to
experiment and fail and experiment some more to push a paradigm farther.

I don't know how successful they will be with this approach and maybe they
will end up ditching it but even if they fail the first time they have the
opportunity to gain valuable experience.

~~~
ramseynasser
Exactly! I'm one of the core devs, and we all see Arcadia as an experiment in
what game development could be. Some people want to expend effort mastering
the tools of the day, and that's totally cool, but we're somewhat more
motivated to spend our time trying new things. Members of the community have
already pushed out a number of games, and their experiences have guided made
the tool better and better.

------
optionalparens
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
Clojure 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.

------
Maultasche
I haven't done much functional programming, so I have a question regarding how
this is done.

From what I understand, functional programming usually avoids side effects, so
mutable data structures are replaced by immutable data structures. So instead
of modifying an existing data structure, a new data structure is created
containing the modification.

So how does this work with games? When you modify the game state, is the
entire thing copied into a new game state? Doesn't that really slow the game
down when the game state is large and changes are frequent? Is there some
trick to this that avoids unnecessary copying?

~~~
matchu
Some immutable data structures implementations perform optimizations under the
hood.

For example, if you have a large game state object with _mostly_ stable
fields, but the position value changes frequently, you don't need to perform a
full copy of the object when position changes. Instead, you could create a new
object that _only_ keeps track of the position field, and delegates all
requests for other fields to a more stable underlying game state object.

You could also imagine an environment that, if you're going to throw away the
reference to the old game state anyway, then it's safe to mutate the object
directly instead of bothering with copies or proxies.

…that said, most implementations—especially if you're not careful—will
probably incur performance costs, and, at 60 FPS, those matter. They're just
not necessarily _as_ bad as you're imagining :)

------
agounaris
Nobody has ever answered the question of the competitive advantage functional
programming gives apart from the opinion that "sounds cool". The principles of
functional programming definitely have their place in modern development but
picking the de-facto tools for a job is always the safest choice when you do
commercial applications.

It's kinda of sad when people treat functional programming not as paradigm but
as a solution to their problems. Sometimes I feel that they think they will
let all of the bugs, design decisions etc just go away, only by using FP.

~~~
rubber_duck
I think that for game dev OOP is a better abstraction than FP.

One of the great things about FP and Clojure in particular was that it showed
me how you can cleanly separates values, identity and memory addresses.

But in games you're often dealing with memory directly anyway and don't want
to abstract that away. And abstracting identity from address doesn't buy you
much because you're always running in shared memory space unlike distributed
systems where it suddenly makes a lot of stuff transparent.

------
automatwon
_First and foremost, simplicity. The code is shorter and more manageable._

I don't know if functional program is SIMPLE as much as it is CONCISE.

I didn't see the word monad, fold, or reduce anywhere in the article. Is a
functional programming language used with side effects and all? There's no
acknowledgment of scenarios where managing the state the functional way can be
unnatural, and require an intellectual hop. Or, alternatively, that this game
in particular lends itself more naturally to the functional paradigm.

~~~
dkersten
Clojure generally doesn't use monads and has its own way of dealing with
mutable state. Clojure doesn't prevent side-effects, but it does make them
somewhat unidiomatic in most cases. In any case, Clojure makes it pretty easy
to write pure-functional code and carefully manage the mutable state and side-
effects that you have.

Having said that, I don't know anything about Arcadia and how the Clojure code
interacts with Unity and how clean the paradigm separation is...

------
AdeptusAquinas
Modern C# only has to be written object orientated if you want it to be, and
works pretty well as a functional language if that is what you prefer.

Biggest problem with Unity and C# is the delay in adopting the latest language
version - last time I checked Unity was C# 5, not 6. Hopefully Unity adopts
.NET Core soon, getting around this problem.

~~~
cableshaft
Did they say they were going to .NET Core? As someone who researched porting
code from .NET to .NET Core, it seemed like a lot of work, there was a lot of
libraries we relied on that just didn't exist in Core, and we decided not to
pursue it within the company at this point. I imagine such a massive engine as
Unity would be even more difficult.

~~~
AdeptusAquinas
I know your pain, and there is also a big shift regarding dev tool chain as
well. But once all thats over, I've found the resulting framework and
experience pretty superior.

Especially when working across desktop/mobile/web/docker domains - using core
everywhere works pretty well.

------
throwaway7645
How mature is the Clojure library for Unity being shown here?

~~~
erik
"Arcadia is still in pre-alpha and highly experimental. We are working towards
a coherent first release, but we’re not quite there yet."

[http://arcadia-unity.github.io/](http://arcadia-unity.github.io/)

Looks like lots of fun to play with though.

~~~
throwaway7645
Thanks! Sounds like a lot of fun, but a gamble to bet a commercial project on.

------
SomeStupidPoint
Just a nitpick: you can live code in imperative languages and functional
languages can require compilation. That has more to do with your design,
framework, and tooling than the language itself. It mostly is a divide between
compiled and interpreted languages, though that distinction gets blurrier over
time.

That said, Im a big fan of functional languages for game scripts (and got in
to that myself using LISP on text MUDs).

~~~
throwaway7645
Can you go into detail on using LISP for text MUDS? I have an appreciation for
text based games. I find the simplicity to be elegant.

~~~
SomeStupidPoint
I was only a lowly content builder and quest manager, so I can't speak much to
how the server mechanics worked.

But essentially, each entity (usually a mob) would have a set of event scripts
(attached to some kind of internal lookup table), and each time an event
happened, it would call the appropriate scripts/function/macro.

So what I did was logic such as "game tick -> wander one step in a random
direction" or "player enters room -> attack", but also slightly more complex
ones such as "combat round -> if low health, flee".

The cool feature of the server was that you could specify multiple options in
the template, and it would randomly pick one for a newly created instance,
giving some variety to behaviors (eg, some guards flee and some fight to the
death). Each instance could also be given a specific one after instantiated,
which was how we constructed special events. (That is, use an existing
template, tweak a couple behaviors of the instance, and then redecorate it.)
This is mostly just a benefit of first-class functions and LISP's ability to
switch strings to code.

LISP was mostly just nice in that you could often one-line fairly complex
behavior, so you could build in-game over telnet.

Honestly, I really miss text MUDs, but does anyone actually want to read
anymore?

~~~
philipov
I too was a mobprogs builder, but I hung around diku-based muds, and none of
those used lisp. I loved the SMAUG codebase in particular. There was a
NO_FLOOR property, and I discovered that there was an brief input delay on
hitting the floor, during which your commands would be completely thrown out
of the buffer. If you made an On Entry script in the destination room to
immediately teleport the player back to the room with no floor, you'd trap
them in an infinite loop that didn't buffer overflow, and completely ignored
their commands. They would fall, hit the floor, and before their input block
had ended, they would be falling again.

Now, did you know that SMAUG's mudprogs ignored level restrictions, but could
be activated by any IMM's force command? So when you force the mob to
mpteleport a player, it doesn't check that you're only level 55 and the
mpteleport target is level 65... so I called that a prison for gods.

I think I spent more time trying to break the code than actually producing
content.

~~~
SomeStupidPoint
For anyone reading: this is basically how all hacking works and why security
is hard -- you have to think out every way several components might interact.

