I worked at Naughty Dog, shipped Crash Team Racing and worked for 6 months on Jak & Daxter.

These are my understandings. If someone there as different recollections I'm happy to be corrected.

The LOD system in Jak & Daxter was based on / inspired by the LOD system in Crash Team Racing written by Danny Chan. The easiest way to explain that system is to imagine a cube with 8 vertices. Subdivide it so it's got 9 quads per face using 48 vertices. Let the artists move the vertices wherever they want. The close up LOD is the full 48 vertices, the far LOD is the 8 vertices. At some distance between the 2 the 48 are interpolated until they match the 8 so there's no popping. You can see this happen in CTR pretty easily if you play the Coco Park track. If you can manage to keep the purple pillars on the left in view you'll see them morph. Unfortunately this video doesn't keep them in view but it shows the pillars I'm referring to

https://www.youtube.com/watch?v=StURmtwJfLk#t=6m30s

Hiding the morph or rather building things that don't appear to morph was a skill the artists learned as they progressed. Jak & Daxter you don't see it much. The first Ratchet & Clank which uses the same tech from Naughty Dog you see it quite often as their artists were new to the technique.

As for GOAL it was my first experience writing a large amount of LISP. Before that I only wrote a few emacs macros. Things I took away from it

* Having your own compiler can be a huge benefit

Whether or not LISP itself is awesome many of the benefits were because we had our own compiler anything we wanted could be added. Live reloading of functions is not impossible in other languages if you have your own compiler.

Another simple example you could specify the byte offsets of fields of structs. As a game programmer that seemed awesome compared to C where you just had to go through contortions and add padding and pray.

* Having a full language for macros is amazing

I'm still surprised so few other languages have this. LISP lets you use the entire language at compile time. Query a database, read a file, emit code. In C/C++ most people use python to generate code in my experience. C++ has the template system but it's arguably not designed to do the things people make it do. In fact I'm surprised there aren't more transpilers from some reasonable language to C++ template meta programming. Even if that was popular though C++ templates can't read files or query databases at compile time.

As one tiny example I designed a particle system. There was an init structure listing all the parameters for particles. To be efficient it needed the list of be in the same order as the fields in memory. The macros I wrote would take an unsorted list and sort at compile time, filling out any missing parameters with defaults so the code that emits a particle would walk straight forward, no conditionals, cache friendly.

In any case I'm still waiting for a mainstream language to offer this

* Having a REPL into the game is cool

You could almost think of working on Jak & Daxter like opening up an webpage in your browser's devtools. A REPL at the bottom you can start inspecting things, changing variables, even more you could replace functions. The whole thing ran inside emacs. You could open a file, put your cursor in some function and press some hotkey to compile just that function live and patch it into the running game. This was better than say Unity in that Unity serializes the entire game, compiles everything, then deserializes back where as GOAL would just compile that one function.

* No 3rd party libraries

I'm not sure this was important back then but nowadays with so much open source and commercial libraries to help make a game it was a problem that the GOAL environment was not really conducive to using any 3rd party code since that would have been in C/C++

* No Visual Studio quality debugger

I've been on lots of projects without a good debugger and it's always been frustrating. Writing your own language from scratch probably means no good source level debugger. From the REPL you could set breakpoints and step through code but it was like using gdb. Sure I get by but not nearly as fast as a real debugger with watches, various panes showing live memory, live variables, conditional breakpoints, etc...

Maybe now a days you could easily make a web based backend or abuse the browser devtools with source maps and remote debugging protocol or something to get a good debugger with low effort?

* Slow Dev system

This might have been a problem that was fixed but when I left you'd start up the game and wait several minutes as in like 10 or maybe even 20 before you could play. The entire AST for the code would be put into GOAL and then the game would be running. If the game crashed you'd get a message in the REPL. Andy Gavin, the guy that created GOAL would look at the message, see the issue, type some magic incantation, and the game would come back instantly. For me though who didn't have a mental image of how the entire system worked most of the time I just had to reboot and wait the 10-20 minutes.

How that was eventually solved I have no idea. Maybe all the programmers internalized the system and could do the same magic that Andy could do. Or maybe Andy found a way to make the system start up faster.

I'd be curious to know the answer.

Of course this was offset by being able to live edit functions for fast iteration.

* LISP can be fast

There's nothing inherently slow about LISP. Maybe most impls are not fast but GOAL was. Jak & Daxter has some of the largest worlds, with the most polygons on the screen and it runs at 60fps on PS2 where as most other games on PS2 run at 30fps or less and far less polygons. That includes whatever garbage collection it used (I honestly don't remember what it did there). In other words, whatever assumptions I had about higher level languages and/or garbage collection being bad for game dev were mostly proven wrong.