Re: [GD-General] Scripting
Brought to you by:
vexxed72
From: brian h. <bri...@py...> - 2002-12-07 03:15:59
|
> I think data description (let alone "rich" data description) is reason > enough to use something like Lua (which started its life as a data > description language). I agree, and in fact that's what I use Lua for right now. It stores my configuration variables, and I also use it to execute extremely crude "level scripts" for some of our 2D games. But I've struggled a bit to figure out how to go past that basic functionality, which is part of the reason that I'm so down on scripting recently =) > I think you're taking on a couple separate issues here, 1) the > language itself, and 2) the development environment (i.e. the > mechanics of how you get your code into the running game). Sure, I kinda tossed them in together, but at the same time, they're both valid reasons why scripting is a pain in the ass for non- developers to use. Lack of a debugger alone can be an absolute killer, especially if you have a huge numbers of scripts and you have some small corner case that only manifests itself under certain conditions. > I can say that about Python (and Lua) with a straight face. Although > "intrinsically easier" is pretty subjective, in the absence of user > studies. I hate to be so curmudgeonly, but I think you're too experienced to make that call =) Even a simple one line bit of Python looks like gibberish to a non-programmer. I mean, this is something pretty simple: data = filter(lambda x: x>=' ' and x<='z', data) Yet you show that to an artist, and they're not going to have any idea what it does. Something as basic as parens for a function call -- or a function call, period -- can be daunting, and this is something most languages will have. Same with this chunk of Lua: function List:reverse() local t,n={},getn(self) for i=1,n do t[i]=self[n-i+1] end -- reverse for i=1,n do self[i]=t[i] end -- copy back end Now, I know that these aren't that obtuse, but they're obtuse enough to a non-programmer that I just think the difference between good C code and the above isn't going to be that huge either way. > I generally agree with your point that the "language" part > of "scripting language" is *not* the killer feature that makes it > worth doing. Right, that's a good summary of the way I feel. > IMO, in order to get designer friendliness and faster prototyping, the > key thing to focus on is the "development environment". (And I don't > mean "IDE" per se; I mean whatever it is specifically that a designer > has to do to see her changes in the game, and all the little > mechanical details of how feedback comes out, and how you debug, etc.) Agreed. For example, a level designer/mapper should access scripting facilities from inside their level editor. Assuming they even need to see the scripting code. > I've never worked on a commerical game whose average edit-compile-run > turnaround was less than a minute (and usually it has been at least 2x > worse than that). One minute, okay. Five minutes, even that's fine. For what it's worth, when I worked on Quake 2 and Quake 3, complete build times were on the order of a minute IIRC, and compile-edit-run was measured in seconds. I don't think anything magical was done for that either -- it was straight ANSI C with the subsystems broken apart into DLLs to avoid interdependencies. But these days, I'm hearing stories about build times measured in the tens of minutes or, in some cases, hours. HOURS. I just find this unimaginably bad, and in many cases it's because of heavy use of C++ templates or STL or other things like that. The rationale is that stuff is bigger, huger, and more complex these days, but at what cost? > The script-whatever-run cycle has the *potential* > to be very quick, although it also tends to get bogged down by > suboptimal process, in my experience. I would argue that it gets bogged down more often than not. When you talk to people that have written scripting languages or used them, inevitably it's trading off one set of evils for another set that are often just as bad and sometimes even worse. > Like, scripting engines where > it's theoretically trivial to inject updated scripts into the running > game, but nobody exposed the functionality in a way that the designers > could use. A simple "load(script)" command that you can trigger from > the console in the running game goes a long way. In general, I think > using a scripting language for a console language is a handy thing. I think this is what Bioware did with Baldur's Gate et. al. > Well, you can do either of the above, or both at the same time, with a > scripting language. (And, as I said, I think there are advantages to > using a scripting language's parser to digest your data.) The main reason I started using Lua for my cvars is that I found I was writing Yet Another Crappy Parser, and figured I'd just Lua handle it. The thing with scripting languages though is that finding the right area to bifurcate is extremely hard. I really think this is glossed over too much. Using our door example, you have a situation where you have to neatly define "What parts of being a door does the script decide; and what parts of being a door does the engine decide; and how do they reconcile these aspects?" And no matter where you draw that line, you incur some kind of cost in development time, run-time cost, robustness, features, etc. At one extreme, the "script door" is nothing but data defs read by the engine, at which point you have very little flexibility since any new capabilities implemented by the engine have to be exported repeatedly to the script designers. "Oh, I can now make doors out of different materials, must support this capability". At the other end of the spectrum, you have ALL properties of the game done in the script, and the engine is solely responsible for low level system tasks like rendering, marshalling input, low level audio, etc. At that point you're also in a special form of hell, because you've effectively exported huge chunks of your engine to the script so that the script can do meaningful work, AND you've put yourself in a position where your primary development pipeline is being gated by scripting tools which have a high likelihood of sucking. And, honestly, if you make any major changes to your engine, you're probably breaking the scripts anyway. > finalDoor = { > type = door, > key = function(opener) > if opener == evil_wizard then > nil > else > redKey > end > end > } That's a slippery slope you walk upon =) > Anyway, I also struggle with the issues you raise. I do think it's > very helpful to know about all the things that are wrong with > scripting languages before deciding to use one, and especially after > you're committed to using one. In this particular case, I went from using Lua to looking at everything else to deciding to roll my own to back to using Lua, all in the span of about a week. It was extremely helpful to me trying to write my own, because it made me acutely aware of all the different implementation and design trade offs that a language has to make, and by extension I learned why different languages are good at different things and bad at others. And that's why I've reached this philosophy now, because once I gave myself the "freedom" to write my own language, I realized that the _language_ wasn't the problem. The language and its implementations can eventually become a problem, e.g. Lua's garbage collector or Python's footprint, but long before you reach that point, the integration and development process issues will become a much bigger concern. I'm quite amazed at the number of developers I run into that use scripting languages but deep down inside still aren't comfortable with how and where they've integrated them into their games, which is why I'm so leery of scripting at this point. You hear a lot about backdoor hacks to get pieces of the engine and scripts to communicate something that isn't cleanly defined by the pre-determined APIs. For many developers, it makes a lot of sense, I just fear for the developers (and games) that feel a certain obligation to be script driven because everyone else. For example, console games -- obviously the mod community isn't going to be targeting console games, so I'm curious to hear why/when/how someone would fully script AI, combat, quests, levels, etc. for a console game. I'm sure there are good reasons, but I'm real curious if the actual benefits derived were worth the hassle (and if they couldn't have been reached some other way). This is a separate subject, but I really do feel that in many ways, games are being overengineered. Tempting technologies like C++, STL, scripts, garbage collection/ref-counting/smart pointers, keep rearing their heads, and they make such promises of how everything will be better, but when you get right down to brass tacks, rarely have things improved. I have a C++ application framework code base, and I have some open source stuff I'm developing on the side that is ANSI C. The latter stuff, without exception, is better architected than the former, because C++ hierarchies have a tendency of "hardening". Code acquires a sense of mass and inertia that makes it difficult to modify, and when you have huge amounts of interdependent code, like a C++ class hierarchy, then trivial changes become non-trivial. STL is the same thing -- it's so great to have something like std::set or std::list available all the time, but holy crap, is writing a linked list REALLY that stressful? Because the last couple times I used STL, the 15 second list vs. the 5 minute self-rolled list time advantage evaporated the first time I had to try to read STL code in the debugger and look at opaque pointers with no idea what died and where. But I was convinced that STL was a "better" way of doing things. Then you start hearing horror stories about build times with STL; rapid rise in binary data size; inability to debug code deep inside STL; etc. and suddenly you find that your project is suffering in many different areas because you wanted to take the easy way out and reuse a very popular and successful library. This isn't about NIH vs. non-NIH, it's about theoretical vs. actual benefits of things that are just touted as "better" without any real objective data to back it up. It's about purity of design vs. pragmatism in development. It's 80s software engineering dogma vs. old fashioned "just getting it done". Are STL and C++ worthwhile if you can no longer have an incremental build cycle? Are scripts worthwhile if you can no longer debug them, or if you spend just as much time dealing with script<->engine communication as you would have just writing the scripted stuff directly into the engine? Is SourceSafe's GUI better than using cvs at the command line if you can no longer check out stuff remotely from home? Is garbage collection really that much better if you now have to start searching for cycles and be real careful about how you allocate objects during run-time, and when you gc, and when/how you delete root objects that can cause cascading gc? Okay, I'll be quiet now, I feel better =) -Brian |