6 ms·
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, a
by reitzensteinm 10y ago
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 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.
- mquander 10y agoThe 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.)
- elcapitan 10y agoDoes anybody here have experience with F# and Unity? Unity uses older versions of .net, and F# is not officially supported, so it's hard to find real experiences with it, although it sounds very tempting. I would imagine that it would be most effective to have the performance-critical stuff in C# and then F# for developing higher-level game mechanics.
- tlarkworthy 10y agoagree, GC is going to slay this approach.
- buzzybee 10y agoI would concur and add that the main risk one runs in deploying any new, widespread abstraction to game code is an architectural meltdown, where perf bottlenecks are appearing everywhere, too many code paths have been locked in by the abstraction so you can't iterate on them fast anymore, you have race conditions you can't analyze properly, etc. Iteration times across the whole development lifecycle are hard to optimize because in the near term the iteration problem is specific to writing basic functionality, then later on it's adding and adjusting a wide variety of assets, and then even later it's debugging and optimizing. Care too much about one and you mess up the others. If you soak up pain up front to keep the core of the code in an unadorned imperative style, crunching on plain data, avoiding deeply nested callstacks or polymorphism, you get a huge assurance that you can handle anything that happens later on - it follows the grain of the tooling and the happy path of the optimizer. The way in which I last approached the live-reload problem was to write a data model, and then bolt a scripting language on to generate data. Then reload the scripts - you get the fast iteration, without being particularly invasive on the main loop. Edit: And similarly I've focused most of my abstraction braincycles on making it easier to access and swap out assets. One of the biggest recurring problems in engine code is deriving runtime assets from combinations of static assets and parameters. This has led me down the road of developing an addressing scheme.
- s_m_t 10y agoI've just started to program a game engine and to my surprise the most difficult to structure aspect of the programming has been essentially, I'm not really sure how to word this, but mapping things to other things. Making sure that a keypress eventually leads to the right function being called is a good example. It seemed really simple at first but then I figured that the keypress shouldn't directly call the function because then you'd need to recode or reparameterize some giant state machine because in certain contexts a keypress can do many things or control many different objects in the game (even controlling multiple objects at the same time, and what if you want to be able to control the game remotely or from two controllers at once?). Before I started I thought the 3d movement and physics stuff would be the hardest... but I've found it was actually pretty simple, I just iterate through a list of objects and just call their respective member functions to make the movement happen and it seems to work fine for now.
- aschearer 10y agoAuthors please heed the above warning. You are entering an extremely competitive, challenging marketplace and opting to play on "hard mode" for limited benefit. Worse you're doing it with your first project. You should focus on becoming an expert with vanilla Unity and shipping as many titles as quickly as possible.
- optionalparens 10y agoI couldn't agree more. If anything, the pleasant experience argument tends to come up more in the context of discussing a secondary scripting language to be added on top of a fast, already working foundation. Even then, you mostly just end up using something reasonably fast like Lua or one of its cousins. I can't see Clojure really being a good fit for any existing engine I am familiar with as a main or scripting language (maybe ClojureScript if we stretch it for something using JS, which I disagree with), and I love Clojure. FWIW, scanning the Arcadia source there's also some garbage being created that can be easily avoided. I didn't really trace to see what each thing was "doing" or if it even runs during a game, but it certainly felt eye opening to me to see lots of temporary garbage created in something that is supposed to be lower-level. I am not sure at this point what would get optimized away anyway (ex: foreach loops, extra tolist/arrays used to create garbage in the past), so here's to hoping the devs just didn't get around to optimizing that stuff away yet. Seems to me you would want to minimize garbage from Aracadia itself given Clojure is going to create yet more, not to mention cut stylistic corners for pure speed in this context.
- ramseynasser 10y agoTo your first point, Mooi is planning on using Clojure as a scripting language. Clojure compiles to CLR bytecode, and is in theory as fast as C# is as a language. Using the idiomatic persistent data structures has an overhead, of course, but Clojure allows you to be flexible with how and when you do that. I wouldn't say Lua or JavaScript are "reasonably faster" than Clojure is on the CLR. To your second point, we're aware that there's room to optimize and we're actively working on it. We profile and optimize our code paths regularly, and the results are often surprising. If there's "obvious" stuff left in there it's because we're tackling bigger fish than e.g. a foreach loop. None of these are show stoppers, in practice, but this is part of why we're in pre-alpha.
- optionalparens 10y agoI am aware of the compilation into CLR bytecode and I've been a .NET user since the beginning, though I don't work with it much these days. The fact that it someone is using Clojure though doesn't mean it will translate always into the most efficient byte code. On the JVM, this is a problem sometimes forcing you to either write your Clojure differently to produce something more efficient, or requiring you to write a bit in Java and call it from Clojure (contrary to amateur practices w/Unity, people do need to share code that is not just abstracted by the engine such as some behavior). The same paradigm would be true of having to drop to C# and then call it from Clojure CLR. The problem here just becomes you get further from what is good about Clojure and instead write a version of Clojure that is closer to C# or something else. Regarding speed, I think you misunderstood part of my comment. I simply mean you pick something decently fast when picking a scripting language with regard to the host language. Obviously Clojure is decently fast on the CLR in theory, but in practice may be another matter given the properties of a game which are far different than general use computing. As for the speed with regard to Clojure, I've covered much of the general stuff in other comments, but I was in part writing to the point of using it independent of Arcadia in a scripting context. For this, I am contending there aren't many advantages to using Clojure over other approaches as a general scripting language for most engines, ex: Unreal, CryEngine, in-house, etc. Unity obviously benefits because of the CLR, but there are still issues with both Clojure CLR and using something that is yet another abstraction on top of Unity as others have pointed out. This makes life hard for newer or less-skilled game devs especially which it tends to sound like the original post authors are in general. More than anything, unless you have unlimited time, do you want to get a game done or do you want to help fix a new runtime? Additionally, I am not comparing Lua to Clojure for the CLR specifically, rather stating that most of the time you add a scripting language to an engine in general it depends to be languages with certain properties. The reasons have little to do with Clojure as a language and more to do with scripting specific needs, which Unity itself doesn't really handle very well depending on how you define "scripting." That is any decent scripting engine must address some of the following below in a game, or it is not a scripting engine but rather just part of the main compilation target. - Support hot code reloading, ex: from file system, user scripts, in game commands, etc. - Compile/JIT reasonably fast if required - Provide bi-directional calling semantics - Easily integrate with the primary host language of the engine - Decent experience for script authors - Easy tool integrations, including with 3rd party middleware - Minimize garbage if generating any, and make collection predictable if possible - Not require the game code core to be recompiled in tandem (a primary motivator for using one from C/C++) Clojure on the CLR certainly does some, but I'd argue not all well to be a huge benefit over C# in terms of productivity, performance, user experience, or user-facing scripting features. Of course there are some cool things due to Clojure's reader and macros, REPL, and so on, but the point is more the aggregate benefits. The reason people use Lua, Squirrel, AngelScript, and many others is not that they are the best, or fastest languages, but are generally good in all those points with regard to the primary language of the engine they are attached. Personally, I'd rather use other languages like Clojure, but there are tons of drawbacks that don't bite you until you are working on a real project, many that I listed elsewhere in this thread. As I noted (and you repeated), I assume the code is alpha and there are still items to address. Nonetheless, most of these things are obvious and easy up-front, and many well-known in the Unity community, so I'm not 100% buying everything is a "later," just some of it. While in a normal game I wouldn't expect various optimizations or micro-optimizations, in an engine you definitely do. Even when working in C or C++, all the engines I've worked on we used our own allocators, minimized general allocations, added indexing tricks, branch prediction and inlining tricks, array packing, alignment tricks, and so on from the start, because that's the job of the engine and the end-user (game dev) cannot optimize away all of those things if the engine is the issue. Of course Unity doesn't do all these things well and things like Clojure layers are a lot further from the actual engine, but I'd argue that it means that everything needs to strive for equal parity or better performance when and if possible. Those are things you design around mostly from the start, the other optimizations that I think you are referring to happen later. I'm simply contending I see a mix of both. Finally, following up again on the use of Clojure, as I've said in this thread, I'm a big proponent of Clojure. That aside, the CLR vs JVM implementations do not have parity because of lack of resources more than anything else. This automatically puts a lot more work in the pipeline and ultimately on the game developer, at least until things mature more. This isn't about using something like Arcadia at all, but rather using it right now given the original constraints and resources the article author mentions or implies.
- jplur 10y agoSo I've shipped a few small games with clojure and unity. GC does come up, but it's very easy to optimize your tight update functions with Unity's profiler. As for finding answers, the clojure CLR interop is pretty similar to JVM. I spend most my time looking at the Unity scripting docs.
- hota_mazi 10y ago> I would be very concerned about straying too far from the garden path while also trying to ship a commercial game. Agreed. OP is choosing the dangerous path of picking heart over reason. It's not just that using a dynamically typed language for a game is suicidal, it's that you don't even have a choice in picking a statically typed language: C++ is pretty much the only credible game in town if you want 60 fps and a chance at not being ridiculed technically before game testers even look at your game from a purely gaming standpoint.
- AimHere 10y agoIt's nowhere near that suicidal. In this particular case, the game is being run using modifications to Unity, a very well-established game-engine, so C++ is already doing the heavy lifting (alongside Unity's way of writing GPU shaders). Clojure is being used in place of the usual C# for game logic scripting and the like. It's much less performance-critical and so using something like Clojure is a lot less nonsensical. Whether they're optimizing for the right things in picking Clojure over some other language is maybe up for debate (I'd guess their way would be easier to iterate changes, but harder to debug, and the clojure-on-unity stack they're using is pretty much alpha quality), but Naughty Dog already showed that commercial games can use a Lisp in a similar part of the stack with some measure of success.
- j_m_b 10y agoIsn't there a good profiler for .NET? VisualVM works well for profiling Clojure JVM code.
- deepaksurti 10y ago>> It's generally a mistake to make the initial development more pleasant at the expense of long term maintainability; Me and my friend are working on this game [1]. I have prototyped all the game logic in Common Lisp (using both LW Mobile trial edition and MOCL). We could really quickly iterate the game play and reach a design where the experience will be fun. But to get it working with 60 FPS, we are writing the game now in Swift. A lot of our game asset pipeline is also in CL and Python. So as per my limited experience, I would prototype the game idea in CL; also use more powerful tools for offline utilities etc but ship the game in whatever is the best toolkit for that platform. In our case, Swift, SceneKit and SpriteKit. [1] http://www.isongames.com http://www.isongames.com