9 ms·
Choosing Functional Programming for Our Game
- throwaway7645 10y agoHow mature is the Clojure library for Unity being shown here?
- erik 10y ago"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 10y agoThanks! Sounds like a lot of fun, but a gamble to bet a commercial project on.
- vonkow 10y agoNot very, according to it's website http://arcadia-unity.github.io/ http://arcadia-unity.github.io/ Also looks like the last commit was 2 months ago, FWIW.
- jplur 10y agoPretty mature. There's open issues, but nothing that hinders publishing to desktop and android. If you like clojure and unity I highly recommend it :)
- SomeStupidPoint 10y agoJust 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 10y agoCan 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.
- escherize 10y agoHere's a talk about it: https://www.youtube.com/watch?v=lql2yFXzKUs https://www.youtube.com/watch?v=lql2yFXzKUs
- SomeStupidPoint 10y agoI 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 10y agoI 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.
- seanparsons 10y agoI'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.
- reitzensteinm 10y agoI'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 10y agoF# 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 10y agoWhere did you hear of the GC improving at all? I've heard vague intentions for years, but never anything concrete.
- jackmott 10y agothey 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 10y agoUnfortunately, 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.
- AdeptusAquinas 10y agoModern 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.
- flukus 10y agoI thought unity was a lot further behind, like c# 2?
- AdeptusAquinas 10y ago.NET 3.5 (so C# 3), so you can use Linq with it. Not C# 5 like I said, sorry.
- jackmott 10y agogoing to be 6 very soon
- cableshaft 10y agoDid 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 10y agoI 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.
- jheriko 10y agothis 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 10y agoAgreed, 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.
- optionalparens 10y agoAs 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.
- everyone 10y agoI'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 10y agoI'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.
- automatwon 10y agoFirst 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 10y agoClojure 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...
- agounaris 10y agoNobody 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 10y agoI 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.
- fatalogic 10y agoWhether 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 10y agoExactly! 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.
- spacepluk 10y agoHi 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,
- Maultasche 10y agoI 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 10y agoSome 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 :)