The Verse Programming Language | GDC 2023

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC PLAYING] [APPLAUSE] TIM SWEENEY: Hey, everyone. We're back to talk about Verse, the new programming language that we've been designing for the metaverse. So Verse is about solving the larger problem of the metaverse. Verse is launching in Unreal Editor for Fortnite. But we have much longer-term and bigger plans for it. Essentially, it's aiming to provide a programming language solution supporting development of many kinds of games and other real-time 3D simulations, supporting a full development cycle of tools and content creation for the metaverse. I'd like to say a little bit about what we see this as, ultimately, because the metaverse is more than Unreal Engine is today. And it's more than Unreal Editor for Fortnite is today. But it's about social interaction and shared real-time 3D simulation, right? The metaverse is about the experiences people are playing today in Fortnite and Roblox and a whole lot more, and what this becomes as it evolves into a medium for billions of people. And we're talking about the metaverse as a long-term open economy. And so when we talk about what we're shipping with Verse today, we're really shipping one thing, but we're designing for a much, much longer-term set of features and set of aspirations for this thing. And the metaverse, importantly, is not just another app platform. When you release an app, you use a bunch of libraries. But you compile one piece of code, you ship it, and it doesn't change again until you release a new version, whereas the metaverse, we think, will be the combination of millions of objects written by millions of different developers-- a lot of code, a lot of content that's constantly being updated-- in which vehicles from one developer, together with characters from another developer, have to work together, even if those programmers have never met each other or never tested their content before. So we're talking a programming world that's quite different than the ones of the past, and one which requires a very robust framework supporting these sorts of usage cases. And so the metaverse needs a special kind of programming foundation, right? We want something, first of all, that's really easy to learn. We want it to be somebody's first programming language, just like JavaScript is to web programmers today. We also want a language that enables us to catch problems at development time before we've shipped content to millions of users. The cost of fixing a problem once it's already shipped are much, much, much higher than catching bugs. So we want a strongly-typed language that we can count on the compiler to guide us on what the problems with the programs are before we ship them. We also want a language that's really conducive to writing lots of modules by different authors which can work together and evolve over time while maintaining backwards compatibility. So this open-world interoperability is a big design goal for the entire system. We're also thinking of a programming framework which can eventually scale to massive simulations. Fortnite Battle Royale is 100 players together in a single shard. But in the future, we might be able to get a billion users together in a single shard. And we want a programming model that can support that. We also want a language, and we've been putting a lot of effort into building a specification with enough rigor that it could be a future open standard that's agreed on and widely implemented by companies all around the industry, just like JavaScript is in a web browser today. So Verse is our attempt at this. And we're aspiring to create a strongly-typed language that's very recognizable to programmers who've used any of the mainstream popular languages today, whether it's C# or Python. We want something that's not too scary but is at the leading edge of compiler technology and being able to catch problems at compile time. So there are several other principles guiding this. And we're kind of learning from the mistakes of the past. We want a programming foundation that is just code, where you're not writing code in one language that constructs queries in another language and converts them to strings and sends them off to a database and then parses the result, where a whole lot of different languages are interoperating through some clumsy interfaces. We want a single language where you can just write code that gets your job done. We also want a language that can scale to transactional programming in the future. If you think about a simulation that might scale, be it far, far beyond the capabilities of a single node in a data center, transactions are the core technology that supported databases scaling up to huge data sets and to huge concurrency. And transactions, we think, will be the future programming model that enables code to scale up without becoming complex. We also are aiming to build a language that can do everything-- supporting code in multiple paradigms, a language for data also. Just like JavaScript has JSON for describing data, Verse has VSON, a subset of language that can describe data accurately. And even things like markup-- there's a markup language embedded in Verse. It's not usable today, but it's in the specification that will evolve in the future, and even more advanced features for the future. We've also put a lot of effort into building a language that's, to a certain extent, timeless. We have this question. What happens if we met some aliens for the first time and compared our programming languages? Well, I think we'd find that we have a lot in common. But they probably don't have 32-bit or 64-bit integers. And so we want a programming language that's free of the temporary constraints of current systems. And to do this, we recognize that we're building in a very long-term evolutionary environment, where we're shipping one-- we're designing a language for the very long-term future. And we've coded in that MaxVerse. And we have a massive specification written out on paper for what we want the language to eventually be. And we're working to that step by step in what we call BetaVerse. This is the beta version of the language that's launching right now. It has a limited subset of those features. But we have a nice clear path for it step by step. We can get closer and closer to the ideal so we don't end up painting ourselves into a corner as we evolve the language, as so many others have done in the past. And we're holding ourselves to very rigorous backwards compatibility standards. Now, these are going to be relaxed during the Verse beta. But when we get to the open metaverse, we really need a programming foundation where your code does not break every time a new version of your metaverse browser comes out or that doesn't differ between different browser engines. You want something that's very stable and very reliable as a foundation for all of our long-term development plans. And so now, to talk about the specifics of the language, I'd like to invite up Phil Pizlo, the director of language engineering at Epic. Phil? [APPLAUSE] [MUSIC PLAYING] PHIL PIZLO: Hey, everybody. So I'm super excited to show you Verse by example. So let's just jump right in. Let's say that you want to define a value, constant value called X, and set it to the value 42. This is what it would look like. And here we've given it the type int. Although it is also possible to write this without the type, if you just say X := 42, the compiler will figure it out that this is an integer. And here we're defining a constant value. Later on, I'll show you how to define values that are mutable, like mutable variables in most other languages. Here's an example of an array. Again, here I've given the type. So the type is square bracket int, which means an array of int. And the value is the three integers 1, 2, and 3. Of course, I can also do that without specifying the type, and the compiler will just figure it out. So let's get into something a little bit more complicated-- functions. Verse supports a function syntax that is very similar to mathematics. So here is just a one-liner function. It'll take an X and return X+1. You could also put the X+1 on the next line. Verse supports syntactically significant indentation like Python and Haskell. So if you have an indented function body below the function signature, everything that's indented stays part of the function body. And the same is true for other block scoping constructs in the language. The language does also support squiggly braces. So you could put the function in squiggly braces if you don't like syntactically significant indentation. Verse functions can be overloaded. Here's an example of a function Foo that takes either an int or a logic. It doesn't even have the same return type in both cases. It could be a completely different function body. If you call Foo with 0, it calls the first Foo and returns a string. If you call Foo with true, it calls the second one and returns nothing. Next up, modules-- modules are a great feature for encapsulation. The easiest way to make a module in Verse is using the directory structure. Within your project, if you have Verse files in a subdirectory, that subdirectory becomes a module. But you can also use modules directly in your code. And this is how you would do it. You use the module macro. Again, syntactically significant indentation means that the A and F members are part of that module. So here I've defined both members public, which allows code outside of the module to reference them. Verse also has structs. Structs are great for just passing around clusters of values with named properties. So here I have a struct that just has one member A of type integer. There's a couple of things going on here that I want to point out. First of all, our naming convention, which is not enforced by the compiler, is that we use capital case for values and lowercase for types. For multiple words, we use snake case for types. So maybe it would be foo_bar instead of just foo. And we use camel case, uppercase camel case, for values. It's not enforced by the compiler. So you can do whatever you feel like. But this is what we recommend. Another thing happening here is that I have given the A member a default value of 42. So if I instantiated foo without specifying the value of A, A would be 42. But here, as you can see on the second-to-last line, I'm instantiating foo with A being overridden with the value 43. So then, later, when I say X.A, I get 43 instead of 42. Verse also supports classes. Classes are more powerful than structs. You can have subtyping. You can have functions. Classes also have-- class instances also have identity, kind of like they do in Java and other object-oriented languages. Here I've just created a class that has no supertype called bar. I've given it a field A with default value 42 and a function. And I've instantiated bar and, again, overridden the default value of A with 43. This is what it would look like if you did subtyping. Subtyping is-- the syntax for subtyping is you say class with a parenthesized clause. Whatever is inside of those parentheses is the supertype. So here bar is the subtype. foo is the supertype. Functions are virtual by-- member functions and classes are virtual by default in Verse. And we require that you use the override specifier when you are intentionally overriding a virtual function. So here we've overridden F in bar to do something different than it would have done in foo. And in order to placate the compiler, we've placed the override specifier on F. Now let's talk about mutability. So far I've shown you a bunch of features where there's immutable variables. And that's not appropriate for all use cases. So Verse also supports mutable variables. And the mutable variable support is really awesome. Here's a really simple example. All I have to do is say var, and X is now a mutable variable. This means that I can change its value whenever I like. The way that I change its value is using the set keyword-- var and set, very simple. So here var X starts out with the value 42. Then I set it to 43. Later, when I say Y:=X+1, the X value that it's reading there is 43, not 42. So Y will have the value 44. The mutability features allow for something we call deep mutability. So here I've created a var map. So it's a mutable map that maps int to int. X starts out being the empty map. The way that I insert elements into the map is using set. So I set X subscript 42 equals 100. That makes it so that X now has a mapping from 42 to 100. Similar syntax can be used for appending to an array. So here I've got a mutable array. It starts out empty. And then I push the value 42 at the end of it. That's what pushing to the end of the array looks like in Verse. Now let's talk about another feature, which is tuples. Tuples are like a very lightweight way of just taking a bunch of values and passing them around together. Here I've created a tuple that has an integer, a string, and an array. I can also give this thing a type if I want. So that's what that would look like if I spelled out the type. Tuples are mostly used as function parameters. That's the main way that you'll encounter them. So, for example, if I say that there's a function F that takes two parameters X and Y, what I'm really saying in Verse is that it takes one parameter, and that parameter is a tuple of type int int. So if I create a tuple like 1, comma, 2, I can use that as a parameter to this function that takes X and Y, and the tuple will be flattened. But parameters are actually a little bit more complicated than tuples. They also support optional named parameters. So here Z is an optional named parameter. It's named. So what that means is that if I wanted to pass a Z to function F, I would actually have to say Z:= instead of just passing the value. And they're optional. If you don't pass the Z, it gets its default value. In this case, the default value is 42. Now let's talk about generics. Verse has a very powerful generic type system. If you've ever programmed in C++, Swift, other modern languages, they also support some variant of generics. Here is a piece of code without generics. So I've created a class called thingy, and it's got an X that's an int and a Y that's a string. Let's say that we wanted to add a little bit of generics to this. Here's what it would look like. So instead of defining thingy as a value that is just a class, I have defined it as a function over type. So thingy is now a function that takes a type and returns a class. And the class that it returns is a class where the Y member has the type t that you passed into thingy. So here you can see that instead of instantiating the object by saying "thingy" and then the squiggly braces, I'm instantiating it by saying "thingy" and then, in parentheses, "string," and then the rest. So I'm instantiating-- that tells us that we're instantiating a thingy where the t is a string. And, finally, on the last line, I've made the function generic. So in the original version, the function just simply took an object of type thingy. Here it's taking an object of type thingy with a generic type. And because I'm using the where clause, the t is inferred. So if I call the function F with some object of type thingy for any type, you can just call this function. And type inference will infer that t is whatever type you were using. Because of our aspiration to have Verse be the language of a unified metaverse with everybody's code all in one namespace, Verse supports a global unified namespace with paths. The top level of a path is a domain. So here are examples of using paths in Verse today. This is basically the Verse include statement. We're pulling in the verse.org simulation module into our scope, and then we're pulling in the Fortnite.com devices module into our scope. And these paths are not strings. They're syntactically recognized within the language. And you'll see more and more of paths in the language as we develop it out. All right. Now let's talk about where Verse really diverges from other languages. Verse is inspired by functional logic programming, which means that instead of relying on Booleans for conditions, it relies on success and failure. So here I've written a Verse program that first says that X is 100 and then says that X is 200. That's a contradiction. So the program will fail. And, in fact, failure is the way that you do comparison in Verse. So if you run a piece of code within the condition of an if statement, what you're doing is you're asking Verse to run that code to see if it succeeds or fails. If it succeeds, then you take the then case. If it fails, you don't. So here the X=200 will fail because X already has a value, and that value is 100. And so "wat" will not be printed. Same thing happens if you use inequalities-- so greater than is a failable expression. If it succeeds, then the if statement will print "wat." In this case, it'll fail. You can also abstract failure out using the decides effect. So here I've defined a function F with the decides effect. And it decides if X is greater than 100. I can call this function F with the square bracket call syntax. Square bracket call syntax in Verse means I want to call this function to see if it will succeed or fail. If it succeeds, you'll get the value. If it fails, well, you have to be in a failure context. And in this case, I'm calling F from within the condition of an if, which is a failure context. So this is the same thing as if I had said X greater than 100 inside of the if condition. And, again, this will fail because I'm calling F with 0, and 0 is not greater than 100. This decides thing is an example of effect specifications in Verse. In Verse, you can specify for any function what kinds of effects it's capable of. By default, functions have a certain set of effects that you'll find useful for most cases. But sometimes you will use effects like decides to broaden the power of the function. In this case, I'm giving the function the additional power to fail if it wants to. And a little bit later, I'll show you another effect that is popular in Verse. OK. Now, this concept of failure is closely tied up with transactions. So if you run a failure context-- in this case, the if condition is a failure context-- that failure context will either succeed as a whole or all of it will fail. What this means is if you run this code, and X is not less than 100, then this effect that you performed will actually never happen. It'll happen, but behind the scenes, we will roll it back as soon as we realize that this failure context is failing. Now let's look at another effect, the suspends effect, which is the way that you create coroutines in Verse. If you've ever programmed with JavaScript async functions, coroutines in Verse work sort of like that. So here I've created a coroutine, and the reason why I've done that is I want to wait for user input. So this WaitForInput, presumably, is another suspends function that I'm calling. And it might suspend for, maybe, multiple frame ticks or something. So if you want to wait for input, if you want to wait for another frame tick, you've got to be in a suspends function, and you've got to call something that will wait. But our coroutines are way cooler than JavaScript async functions because we've brought in all of the power of SkookumScript's structured concurrency. So here's an example of how you create coroutines in Verse. On the left is the block construct, which doesn't really create coroutines. It just runs whatever-- the Coro1, 2, 3, 4, in sequence synchronously. But if I say "sync," then these four coroutines will be run concurrently to one another. And the sync clause will return once all of them are done. And keep in mind that any of these things could be waiting for input, could be sleeping, could be doing whatever they want. Race is another construct. This one's really fun. Race means run a bunch of coroutines. And whichever one finishes first wins, and the other ones are canceled at that point. Rush-- similar. It runs until one of the coroutines finishes. But then the remaining coroutines that took longer are allowed to finish asynchronously after the rush statement returns. Finally, the branch statement creates just a single path of asynchronous execution. So here Coro1, 2, 3, 4 are running one after another, but concurrently to the code that used the branch. To make the race construct and this idea of cancelling coroutines even more powerful, we have a defer statement. You don't have to use it in a coroutine. Here's a simple example where I'm printing "hello world!" even though the code is out of order. The reason why this works is if you have a defer statement, then the code within that defer statement will run when the scope that you're in exits, no matter how it exits. So here, presumably, after Print("hello"), you'll return or something. So then it will print "hello" and then will print "world" because printing "world" was deferred. So this is a goofy way of printing "hello world!" using defer. But this is where the construct actually becomes useful. And that's if you use it with race. So as I said before, race will run the various coroutines. In this case, there's two coroutines. One coroutine is the one created by the block construct, which defers thingy and then does SomethingSlow. And the other coroutine is the SomethingFast coroutine. As you recall, race will run until whichever coroutine finishes first, and then the other coroutines are canceled. But the defer statement ensures that when that first coroutine is canceled because it was too slow, it will run the thingy function immediately upon being canceled. So this lets you manage cancellation in your code in some way. So it's not just that your coroutine goes away. You can actually run some cleanup code. Now let me get into my favorite feature of Verse, which is the for loop. Here is a very simple for loop. I'm just using a for loop here to iterate over an array. This does what you would expect. It iterates over the elements of SomeArray and prints all of them. But the for loop is kind of like a query. Because of the functional logic power of the language, it can do some of the things you would expect from a query language. So, for example, I can throw in an additional condition here. This will print all of the elements of SomeArray that are greater than 100. Or this will print all of the elements of SomeArray that are not equal to 100. And you could layer these conditions on top of one another if you wanted to. Just before I show you some more crazy code, here's another simple example. This will print the integers from 1 to 200 except for 100. All right. Now let me show you the really cool example. So this example is taken from a Minesweeper game that we wrote during one of our Verse-- that one of us wrote during one of our Verse game jams. So to set up Minesweeper, you have to compute the adjacent mines for every cell in the Minesweeper table. And that's kind of annoying to write because you have to iterate over all of the X coordinates of the map, then the Y coordinates. Then you have to iterate around whichever cell you're in. And, of course, you could be at a cell that's adjacent to the edge. So then, it doesn't have all of the adjacent cells you'd expect it to, so you have to do some bounds checking. In Verse, you can write that entire loop just as a single loop without any nesting. The way you do that is first, we use the Y->CellRow:Cells construct to say, I want the index in the array and the element in the array of Cells. So Y is the index in Cells. Cells is a two-dimensional array. And CellRow is the element. So CellRow ends up itself being an array, a row of cells. But without even having to go into a deeper loop nest, I can, within that same for loop, say, well, I want to grab the X coordinate and the cell out of CellRow. So, again, X ends up being the index in CellRow. Cell is the value at that index. So now, with just those two statements, within the rest of the scope of the for loop, I have the X index into this two-dimensional array, the Y index into the two-dimensional array, and the entry. But wait. It gets better. I can then use the range construct to loop even more within the same loop. Here I'm looping over all of the adjacents-- so all nine adjacents-- by just simply saying X-1..X+1 and Y-1..Y+1. And then, when I access the Cells array, notice that array accesses use the square bracket syntax. The square bracket syntax is a failable expression. When does it fail? Well, it fails if the indices are out of bounds. So because all of the things in for loop clause are failable conditions that, if they fail, the loop just doesn't consider it, this means that the loop will automatically skip the out-of-bounds cases without you having to say anything about it. So that's how you write the Minesweeper setup in Verse, just in a single loop without having to use any crazy nesting, thanks to Verse's functional logic power. And with that, let me talk about some future plans. So we're going to bring lots of additional language features on top of what's already there. So right now, it is still a smaller language than what we hope for in the future. As Tim said, right now we're shipping BetaVerse. And we're working incrementally towards the MaxVerse vision. Additionally, although right now the language is only built into UEFN, we eventually want to build it into Unreal Engine as well. And this isn't to replace Blueprints. This is to augment Blueprints. So if you love programming with Blueprints, keep doing it. If you want to program in a scripting language, Verse is coming. We also want to release the language implementation under a permissively-licensed open-source license so that other people can use it for whatever they like, whether it's a different game engine or something not even game-related. The current implementation is still early days in terms of performance. So expect lots of performance improvements to come. Also, right now, we're shipping a relatively simple gameplay framework with Verse. But we're going to grow that and ship a much bigger framework in the future. And on that note, let me turn it over to Tim Tillotson, our gameplay engineer director. [MUSIC PLAYING] [APPLAUSE] TIM TILLOTSON: Thanks, Phil. Let's talk about the Verse API. So much of what I will share today is really forward-looking. We have a lot of plans that we'd like to do, a lot of things we've prototyped. The API is currently in beta and will be for a long time. We strive to have a public stable API, but we reserve the right to change things throughout beta as we need to. If we deprecate things, we'll try to do it like we do with UE. We'll do it in phases, or we'll provide some easy way for you to upgrade your code. So this is kind of a comparison with the game metaverse to the world wide web and how we envision it. At the high level, we want to make creating user games and simulations is easy to do it is to create web applications today. But to do that, you have to have this common set of APIs you're building on top of. And so initially, though, those APIs often start out very custom to the browser or the simulation engine that's created. So we saw a lot of things-- with web browsers, you would find kind of very custom APIs. But, eventually, you'd find an open spec that many of them implement so it's easier for people to write applications against. We envision the same thing will occur here in the games and simulation space. And, eventually, you'll have users build their own custom community APIs on top of that. And so we start with this phase where we have proposing your individual standards that you implement that solve the problems you need to solve. An example is QUIC was implemented by Google and Chrome back in 2012 to speed up how the browser talked to their web search engine. And then that became the basis for HTTP3 almost a decade later. So we're proposing Verse as an open standard. And we'll hope that also becomes adopted, along with many of the other 3D standards we have out there for scenes and 3D models. Much like the JavaScript VM empowers a lot of the web content logic, the Verse VM, we envision, will empower a lot of the game simulation-type logic. And we open it up for others to use in those same game simulation engines as well, beyond Unreal. And we also want to extract a lot of the hardwareisms so you can focus really on making the games and what you do best. So talking about the API we have today, really, the initial API is built around Fortnite Creative. And so these are just a variety of the different genres that people have created games in inside of Fortnite Creative today. And the scriptable device is kind of how we're first connecting Verse to Unreal and to Fortnite. As we look forward over the course of this next year, we want to allow you to also script components so you can build up individual objects and build scenes and build much richer, deeper experiences. We also plan to add a bunch of features which will enable new things that are more challenging to do today with the limited API we provide. Looking forward a year or two, we also want to make Verse performant and work on gameplay systems so it's easier to do things like physics, custom vehicles, those kind of deeper high-performance operations. But long-term, we really want to make Verse able to run AAA games. And so it's a lot of work. We have to get here. And before we'd recommend people using Verse and UEFN in, say, a AAA game, we want to do that inside of Fortnite ourselves. And so we've got years of work ahead of us to do that. But there are many places where a AAA game would want to say, OK, let's make a limited experience to expose our IP to the millions of Fortnite players-- and so a lot of opportunity here for us to decide what's the right time for you to jump in and try out Verse and then use it in your games. So there are a few differences between UE and UEFN and how our guiding principles work. First of all, a lot of times, in UE, you have to go and decide what you want to replicate, write a lot of code that kind of connects pieces together. With UEFN and Verse, everything is replicated from the get-go. So it's simple to approach, very easy to jump in, in an hour of code, write something that is playable. We want to be able to constantly evolve. So Fortnite, we update every two weeks. We want to be able to update games very quickly and let people kind of iterate in that space with their players. We want to have this world where people can publish something, and someone else can use it and kind of have this back-and-forth iteration occur, much like happens in the web space. And so this really rapid iteration of game content is what we want to enable in this space. So at a high level, we divided the Verse API into three namespaces. There's Verse.org, which contains kind of the game-agnostic APIs that we will submit as part of open specs. There's UnrealEngine.com, which contains kind of the Spatial Math UI, those types of things which are very specific to the Unreal Engine. And then there's Fortnite.com, which is the APIs that are largely specific to how Fortnite wants to do certain things, like vehicles or characters. And those will largely always be contained inside of Fortnite and UEFN. So this represents roughly the high-level overview of where the APIs exist today. So if you download Unreal Engine for Fortnite, this is where you'll see the APIs exist. Instead of Verse.org, you'll see Math, Containers, Colors, and things that are agnostic for Game Engine but are generally in use in simulations like Player and Team. UnrealEngine.com, we have things like diagnostics. Most of our diagnostics today-- and debugging really is kind of this printf-based diagnostic debugging-- we pipe that from the servers down to the editor. So you can at least see it in real time, what's going on in your game simulation. Long-term, though, we have other plans to improve that quite a bit. The Fortnite API right now is really around these creative devices. We have a few things we've exposed with characters and vehicles. But there's a lot more we want to express in the future here. And in the very near future, we plan to expose the ability to script AI. So I want to look a little bit further out, what we plan on doing this year as well as in the future. And so I went to one of the indy showcases last night ready to play a lot of games. And I would say there's only a small percentage of those you can build in UEFN today. And that's because a lot of them want things like persistence. They want things like basic input and camera control. And so these are the type of features we want to add over the remainder of the coming year. But the majority of our internal tech focus is going to be around the Scene Graph. We want to let people build prefabs. We want to let people customize weapons and abilities. We want to let people put scripts on objects, build objects, and build out scenes-- and so enabling this really rich environment for people to share and build content, and then I think things like debuggers, performance profiling, and also analytics so you can see what players are doing with your game. So a little bit of detail into what we're looking at on the Scene Graph, and some differences with, maybe, other Scene Graph implementations that are out there-- the most important is we are looking at how we can have a public API that you basically say, here is the things I want other people to be able to query in the Scene Graph, and these are the things that I want to keep internal so we can iterate on it internally and change it next version and not have to worry about breaking anybody who's using our API. On the research side, we're looking at things that you find in UE, like level instances, layers, variants, other ways in which we're composing content today, and see if there's better ways we can merge and undo those operations, both in design time as well as at runtime, ideally so you can make changes to your scene dynamically, much as you have web styling today on web pages. So I want to walk through a demo of creating-- adding Verse code to a Fortnite Creative game, or, in this case, a new UEFN game. So you create a new Verse device by inheriting from creative_device. In this case, I've created an escape_sequence_device. And the Fortnite Creative devices today are just this bundle of logic that you kind of drag into the scene as an object. In this case, you'll see kind of this little console here that represents your script. Inside of the script, you can add editable properties. In this case, we have a player spawn that shows up as a property in the scene. You can then modify on a per-instance basis. So once you've created that class, then you can override the OnBegin method-- or, in this case, because it has a suspense effect, it's a coroutine-- and then add your own custom logic. In this case, we'll spawn an escape sequence that the player will then run through. So in this case, a little bit into the race method that Phil talked about, I have the escape method we run. And then we're also waiting for the player to respawn. And so in this case, the escape sequence shows a message. And then if the player respawns, we run the defer block to hide that message. And so you'll see in the game later-- the little demo that I run through here-- pretty much any place in that, we should be able to have the player respawn. And the defer blocks will cause it to kind of reset and be ready for the player to start that sequence again. And so these defer blocks can be composed in nice ways so that you'll notice they actually go back up the stack. And so the last defer block that was run-- or placed on the stack will be the first one that's run. So little caveats about the scope of this demo-- this is based on the Verse Parkour game template, which is in UEFN today. All the code and level edits are made entirely by me-- so lots of programmer art. A lot of things aren't polished like an artist would do. I've imported a few small sounds and VFX. But I expect that the experience that I've shown you-- will show you here is roughly what an experienced developer who knows UE, knows the toolset inside of UEFN, and is familiar with the Verse code will be able to do in roughly a day or less. [MUSIC PLAYING] So here we tell the player go grab the stolen files, give them a little indicator to show them where at in the level, and then wait for them to enter that area. So once they've grabbed the files here, now we delete the file and then spawn some AI to harass the player, and then wait for them to enter the rooftop area. Once they've entered that rooftop area, we spawn some more AI to continue harassing the player. We start the building on fire, and then wait for them to trigger one of these other conditions-- in this case, they've entered the safe area-- and then prompt them to enter the getaway vehicle. This could be many branching conditions you have in gameplay code. I've only done a simple one right here. So once they jump on the car here, the getaway vehicle, I basically have a little scripted animation you play. And I play a custom cinematic cut scene here as well. And then give the option to jump in a helicopter. And if they do jump in this helicopter zone, we'll place them in the seat of the helicopter and wait for them to enter the level outro area. [EXPLOSION] And then, when they do, we play the outro cinematic. So that's just a small sample of what's possible with Verse in UEFN today. And this is part of just a much larger ecosystem. Please see all the other UEFN announcements they've made about ecosystem and other things that we're enabling in Fortnite. We have years of development workplan. I've only talked about a very small portion of what is on our slate. But really, we want to iterate with Verse and with UEFN as you as a community. Now the tools are out there, there's so much we have planned. We really want feedback as we go through and iterate in this space. So I'll give a shout-out to the team that has worked with us over the last couple of years to bring these things to you. And now we'll turn the time over for Q&A and invite everyone else back out on stage here, along with Andrew Schneidecker, one of our Verse developers. [APPLAUSE] PHIL PIZLO: So let's see. Yeah, go ahead. There's a mic. Where's the mic? There it is. Could you go over to the mic? [AUDIENCE CHUCKLES] Just so everybody else can hear. TIM SWEENEY: If folks just want to line up with the microphone, ask questions. AUDIENCE: Hi there. I'm just curious to see where Verse fits in in the current Blueprint/C++ ecosystem. Because I've heard rumors that you're basically sort of pushing Verse as a third wheel to complement both of them rather than replace C++. Is that true? PHIL PIZLO: Yes. Yes. TIM TILLOTSON: Yeah. A good example is, in UEFN, we can't expose native code like C++ to the platform owners. And also, deploying C++ on servers is dangerous. There's a lot of security holes in C++. So Verse is a very high performant work-- we plan it to be a very high-performant language that we can run on our servers. And so it can do a lot of the things that, today, you can only do in C++ in UE. AUDIENCE: All right. Thank you. AUDIENCE: So I actually had a bit of a syntax question, earlier, about the decides keyword. I noticed that the function that had decides, essentially, if it failed, it was going to evaluate as false if it was in some kind of a decision context, I think, is a word that you used. My question is, so what's the purpose, then, of the logic type? I saw that it sort of is like the replacement for Bool. Wouldn't a function that decides-- why doesn't it just return a logic type instead of having the decides keyword? PHIL PIZLO: If it returned a logic type, then, after calling the function, you'd have to use question mark to turn the logic into success or failure. So the convention is, if you're returning Boolean, you almost always make the function decides. But logic is still useful if you want to carry around, say, an array of Booleans. Then you would use logic. AUDIENCE: So is there traditional Boolean types in Verse? Because you were saying that, in an if statement, it's essentially, if it succeeds, then you do the code. And if it fails, then you don't. So is there a traditional Boolean type in Verse? Or is it all just this failure and success? PHIL PIZLO: There's no Boolean type that feeds into control flow. So if you're doing an if, then the if is based on the success or failure of the expression in the condition. But there is a traditional Boolean type in the sense that logic can be true or false and can be passed around as a Boolean. AUDIENCE: And I just have one final follow-up question. So this success-and-failure system sort of seems like it replaces the traditional exception system present in languages like Java and C#. So in this case, we wouldn't really have try-catch blocks. It's that the whole language is built around success and failure. So if you have an exception, it acts the same way as if the expression failed. Is that correct? PHIL PIZLO: It's similar. The difference is that, with exception handling in most languages, if you look at a function, the points in the function where an exception can happen are implicit. Like you call a function foo. Could it throw an exception? But here, in Verse, if you call a function for the purpose of determining if it decides or fails, you have to call it with the square bracket syntax. You have to be in a failure context. So there's really no completely implicit control flow here. You can see all the points in your program where a failure could happen and the code you're running could terminate early. AUDIENCE: And then I imagine it's a lot more performant than traditional exception handling in other languages. PHIL PIZLO: Oh yes, yes. AUDIENCE: Thank you very much. AUDIENCE: I had a question about under the hood. Is all of this compiling to native? or running in a virtual machine? or what? PHIL PIZLO: Right now, it's compiling to the Blueprint VM. That's not the long-term strategy, but it works great now. AUDIENCE: And is there any plan for supporting FFI-- Foreign Functions-- or anything like that? PHIL PIZLO: For the purpose of us building our framework, yes. When it's released as part of Unreal Engine, yes. You just won't get FFI in UEFN because of the security downside of letting you ship C++ code to our servers. AUDIENCE: Thanks. AUDIENCE: Hi. Just a high-level question. When you set out architecting this language, what was it about existing languages that was uneconomical or insufficient for this application you're calling the metaverse? Very high-level question. TIM SWEENEY: You know, there's really one driving force. It's that we thought it would be very hard to retrofit an existing language to support the full usage case requirements of the metaverse. The two big constraints here are, number one, we need a language that can scale to massive open-world programming where potentially millions of modules by different authors evolve over time, independent of each other, while maintaining interface compatibility. To do that, well, you need an expressive type system that goes rather beyond what even C# and Java have done. Another big consideration was a desire to implement transactions is the solution to concurrency in the future. If you look at how all existing MMOs and other games with massive simulations have dealt with concurrency, they just push a huge amount of error-prone work on the programmer where you're both writing local game code to run on your current node, but you're also sending messages to other nodes in a data center to tell different nodes to do different things, and you're kind of writing your own manual and negotiation protocols for making cross-server transactions or cross-server communications work. And it's all very error prone, unscalable, and seems like a completely unworkable solution for something as open-ended as the metaverse. And so we looked at transactional memory as the solution to that. There's a 20 years of great research, going back to the Haskell programming language on transactions, and we felt that the task of retrofitting an existing language like C# would just not be practical. And we also looked at practical language-- well, engines such as Unity's efforts to adopt C#, and recognized that unless there's something that's really dedicated to solving these problems, it becomes incredibly hard to maintain a third-party integration to a language ecosystem like that. So that, plus just a general desire to clean up some of the foundations of programming, led to the decisions that got us here. And the desire to adopt logic programming features-- some of this fancy "failure is control flow" stuff that we've talked about and the new iteration primitives, there's a lot of expressive power there. We've only barely scratched the surface of what's possible. And over time, that will become more and more apparent, and I think will kind of be a direction that future languages and even existing languages adopt more and more. And we thought it would be good to do that once and cleanly rather than trying to retrofit it over time later. AUDIENCE: Hi. So it sounds like the Verse VM is either in partial work or not started at all. But will that be as permissively licensed as the rest of the Verse language spec. And if Verse is a compiled language, is it going to be compiled to a IR form? Or is that going to translate into something more where the verse VM is directly interpreting it? PHIL PIZLO: Good question. So we intend to release the Verse VM with a permissively licensed open-source license that would make it easy for anybody to use it in their products. So that's one thing. As for what it will compile to, we're still in the research phase of deciding to what extent it can be ahead-of-time compiled versus to what extent it will benefit from more of the Java style just-in-time compilation. And simultaneously, we're going to make sure that it has a really fast interpreter for all those cases where native code or JITing just wouldn't have been practical. AUDIENCE: OK. And secondly, on the language lifetime-- because you talk about a timeless language or a language that has heavy extension-- what is the support for macros or things like quotations and splices in a safe language like, say, Scala, where they have heavy support for language extension to allow for some internal DSLs that allow for some of that extendable functionality that you might want to see in a language like this? Because if you really want it to be code as one, you need support for embedding other types of formatted data. TIM SWEENEY: Yeah. So on the front of macros-- you know, Reynolds, the old computer scientist, wrote down their Reynolds' abstraction theorem, saying, basically, if a language has the capability of doing something cool for itself, it had better open up facility for abstracting over that feature for users. So we have expressions, so we'd better have a variable so you can abstract over values. And we have formulas. You'd better be able to write functions to abstract over values. And macros are a way of abstracting over syntax. So we think that's important. We have just kind of a strawman plan for going all the way down the macro rabbit hole in the future, with the Scheme-inspired hygienic macros. C++ programmers are horrified to hear about macros. But actually, there are languages that have done macros in a completely clean way that avoid the pitfalls of weird string-splicing operations and accidentally aliasing names. There's a really great methodology for that from other languages. We have a plan for the whole thing. And we're not sure exactly how far we want to go down that path. We want to at least get to the point where users-- if you saw the for loop here in Verse, well, that's a special construct we made on arrays. But the for loop you saw in these slides is actually just using a native macro. There's a syntax for the macro. It's some name, parentheses, some values, squiggly brackets, some expressions. And that's the format for a macro. And so it's already designed to accommodate macros at a fairly fundamental level. We definitely expose macros for creating iterator type constructs and formers and containers of all sorts. So if we can write a fancy syntax for arrays and you create a cool tree type, you should be able to write a fancy syntax for trees. But we're not sure how far down we'll go. It gets a little bit dicey to pick apart that abstract syntax tree of a language and casing over special cases on a macro. And when you get down into those domain-specific languages, they're just built from ad hoc syntax. You kind of have to ask, is this really a language? Or have we just done crazy tricks to stick other languages in the language? So I'm not sure exactly how far we'll go. But we'll definitely go pretty far. AUDIENCE: OK. Thank you. AUDIENCE: Are there plans to be able to implement Blueprint nodes like you can do with C++ with Verse. PHIL PIZLO: We've thought about that. But we don't have a concrete plan of exactly how we would do it, what it would look like. AUDIENCE: OK. Cool. Thank you. PHIL PIZLO: That's a great idea. TIM SWEENEY: Yeah. Just one of the things we're thinking through as we're developing all of this is the long-term integration plan for Verse into Unreal Engine and how it coexists with Blueprints. Right now, everything's layered on top of the Blueprint virtual machine. So, you could theoretically make these things interop more so than we have. But one possibility is to, as we're building this new higher-performance virtual machine, layer both Blueprints and Verse on top of that so Blueprints become kind of a visual form of the same language that's Verse and do more to align those. And we've also considered other visual programming directions along those lines. That's an active research topic that we're going to be experimenting with quite a lot over the course of the next year or two. AUDIENCE: Thanks for the talk-- really interesting. I like your transactional approach. It reminds me a lot of Clojure's implementation if you've seen that one. One question I had was you seem to be leaning pretty heavily into kind of pure values and pure functions. And I was wondering if that was aimed towards multithreaded scalability in the future. Because I know Haskell and languages like that have derived a lot of benefit from that kind of being their basis. PHIL PIZLO: So for us, the basis is that we're actually going to make transactions over mutable state fast, hopefully. So the language doesn't quite force you to write pure code the way that you would in Haskell. It invites you to write very traditional, object-oriented, imperative code. So I don't think that we're viewing the pure features of the language as a performance optimization for transactions, although they certainly could be if you used them that way. AUDIENCE: OK. And a second question if that's OK. Have you looked at-- because you're talking about all of this code sharing for, like, thousands and millions of users, have you looked at alternative forward looking ways of storing and sharing that code, things like what Unison is doing with kind of hashing abstract syntax trees and sharing things that way for providing greater scalability than traditional text-based sharing provides? TIM SWEENEY: Yeah. There are really two ways of doing code sharing, as we see it, in the metaverse. The traditional way is, you want to use a bunch of libraries? Great. Well, you copy those into your directories. And now you have a separate copy of the library. And you can modify them however you want. And they never change. And now they're your problem to maintain. Yeah, that works for some things. But we think the much more common approach to sharing in the metaverse will be different authors deploy their own modules and expose them as public components of the metaverse. You see, in Verse, there are public and private declarations and variables. Well, in the metaverse, we take those things for real. If you release a public module, that means any other programmer in the entire world will be able to access your module by its path. You'll have a path that might start at Fortnite.com right now, and then go to your creator name, and then have some directories underneath it. Well, that's your module that you've released publicly. And the intention is that the Verse publishing system has backwards compatibility constraints. If you publish a version of a module that says it adheres to some type signature, it exposes some classes and some variables, then all future versions of that module must be backwards compatible with that public specification you made. You're kind of giving the public a promise that your public interface will not change. And in that way, modules can evolve over time while remaining in place and being addressed in place. And we think that that's a really interesting way to allow the metaverse to evolve, where lots of authors are collaboratively adding lots of different features and capabilities and each accessing their things in place, and especially when you get into shared state. If one person creates a scoreboard that supports lots of different types of games, and other users tie in to that, you're not creating your own copy of that scoreboard. You're talking to the global scoreboard. It's another idea in the metaverse, is that, eventually, global variables will really be global variables. There is one in the whole world. And everybody could access it if you exposed it that way. So the intention really is to have a programming language framework that, writ large-- and what we're shipping right now doesn't implement this concurrency model or this shared data model, although we have long term intentions to move in that direction with the idea that the metaverse, to the programmer, looks kind of like this massive computer that runs very, very fast because it's a whole data center-- or many data centers-- full of computers, but otherwise looks single threaded because this transactional memory system is sequencing all of your gameplay updates through it as it goes. And everybody's code could potentially interact with anybody else's code. And optimizing your code is really about maintaining data locality. So there's a lot of really, really long-term thinking about all of this that feeds into how these systems, especially modules, will interact. AUDIENCE: Interesting. Thank you. AUDIENCE: Thank you very much for the show. You're amazing. And some of the questions that have already been answered. But I just want to confirm, if I understand correctly, it seems like Verse first compiles to bytecode and be processed by the Blueprint engine. And if so, do we have any data for the comparison with some popular scripts we are using [INAUDIBLE] like Python and Lua? And then something like you mentioned, like if [INAUDIBLE] run into the trap after global log, like Python, we are doing it-- we have just been trying it for years. But it sounds like it would be [INAUDIBLE] global log there, right? Like if the restriction of Blueprint engine are-- PHIL PIZLO: So we're running on top of Blueprints right now, but that's not the long-term plan. So the Verse VM that we are building is just going to be multithreaded from the start, basically. AUDIENCE: I see. PHIL PIZLO: And the key thing that saves us compared to Python is, number one, Verse is not nearly as dynamic. It's not like an object is a dictionary. So concurrent updates to the object from multiple threads are not as challenging for us to implement as they would be for a Python implementer. And the other thing that saves us is we have transactions. So because transactional semantics is woven deep into the language, even if updating a language required updating a dictionary, we would just simply do it in a transaction and avoid all of the locking problems that you have in Python. That being said, right now, the performance-- I don't actually know, off the top of my head, how it compares to Python or Lua. It's still early days. So the performance now is not really predictive of what the performance will be. AUDIENCE: OK. Thanks. Very helpful. AUDIENCE: Hi. I'm really excited. The first question would be, have you given any sort of thought to maybe not functional logic programming, but more functional programming concepts? Like you already have the effects system, which is awesome. But have you given more thought into linear types, dependent types? And I did see, earlier in the talk, that you just briefly mentioned proofs. So is there any thought into those more-- like supercharging the compiler that way with those functional concepts? TIM SWEENEY: Sure. I'll talk about some of our forward-looking thoughts and all of that. First of all, yeah, there is an effects system in Verse. And there are a bunch of different effects. And you can combine effects. And when you say what things a function can do. And when you write a function that promises to have no side effects, then the compiler really checks that and gives you an error if you violate the promise you're making. So the effects are actually part of the Open World type signature of a function, are enforced by the language. And the effects system enables you to say, well, this is a transacts function. That means this function can read and write from memory. But all that reading and writing can be done within a transaction because the transaction system under the hood can speculatively run this code and either commit it to the global heap or it can abort it and have no changes made at all. There's different points in the effects lattice where there's pure functions which have no side effects at all. And so you can write pure code like you can in Haskell. And then there's even total functions, functions which are guaranteed to produce a result in finite time given the right amount of memory. There's a lot of thinking and planning there around the type system, which is-- well, it's a big topic that could be-- it could have a developers' conference of itself. But we plan to go a very long way with the Verse type system in building a type system that is statically verifiable and is more powerful than typical type systems you see in languages today. One aspect of it, which you saw a little bit of already, is dependent types. Instead of templates as in C++ or generics as in C#, you can just write a function that takes a type as a parameter and returns a class as a result. And a generic function like that, it's just a normal function. And types are just normal values. And the compiler, over time, will do more and more compile time reasoning about complex sets of value constraints. In C++, you have this idea of constexpr, where you can have a function that can run at compile time. If you give it a constant parameter, it will return a constant result. Well, Verse ultimately has-- we've designed a much more thorough system for taking that idea even further. It senses type checking, dependent types, and some very interesting other features. I guess I've only just given a little hint of it. I can't really go into a lot more detail there. But there's going to be some very interesting stuff happening. And I guess I should just mention, since you opened the door-- AUDIENCE: Sorry. TIM SWEENEY: (AMUSED) No. It's a really interesting topic. It's funny. Very few practicing programmers know about that. But there's this idea of proofs as programs that's one of the big topics in type theory, if you have ever taken a type theory class, that if you have a type system that's designed in a very particular way, then what looks like normal types in C++ becomes, actually, a much more expressive and powerful thing at compile time. A type system that's designed in a very certain particular way can actually express proofs about what can happen in a program as it runs. And for example, you can write a sorting function whose return type is promising to return an array of sorted integers. You can represent that at the type level. And then a type checker can actually type check. When you write the function, you weave in some proof code along with your function declaration. You can actually prove to the compiler that your function actually sorts integers. So if the compiler doesn't beep, then your sort function is guaranteed to be bug free. That's one of the really interesting topics of advanced computer science. And I think parts of this are on the verge of going into the mainstream. And this is an area that a lot of the Verse research team-- some of the greatest programming language luminaries in the world have joined Epic over the last few years, like Lennart Augustsson and Simon Peyton Jones, Rajat Jalal, and some other of the best, most incredible language folks in the world have just collaborated academically on the Verse paper in recent times. Like Guy Steele from Scheme and JavaScript and other previous language efforts is a contributor to the Verse paper. Putting a lot of thought into how to build a language and a type system that's not just some arbitrary programming language designer's fantasy but is based on these really solid foundational underpinnings of proofs as programs and of type theory. So that what we're building is not just another arbitrary, funny programming language, but is something that really has a direct relationship to mathematics and logic and proofs in a way that, as I talked about at the start of the talk, if we met up with aliens, when you compared our programming languages, I think, if the alien civilization is sufficiently advanced, then they'll have actually explored and filled out all these kinds of language features that you don't find in C++ or Java or C# but you do find in a lot of research languages. They'll have sorted that out. And hopefully, Verse is one of the languages that will contribute to bringing these ideas into the mainstream. AUDIENCE: Thank you so much. Hopefully this one is a bit quicker, but-- PHIL PIZLO: Hold-- AUDIENCE: I assume, right now, because it's-- you gave me a lot of time, so I'll-- PHIL PIZLO: Let's just-- we're a little bit over time, but let's just get another 10 minutes of questions since it looks like there's a lot of questions. I'm sorry. I didn't mean to cut you off. I just wanted to call that audible. [CHUCKLES] Go ahead. AUDIENCE: I'm wondering-- I saw, on one of your slides, you talked about the idea of a metaverse browser. And I just wanted to understand a little better where you see Verse running. Is it on client devices, or on the server, or both? And how is that managed? PHIL PIZLO: Eventually both. TIM SWEENEY: Yeah, yeah, and magically so. So the idea-- I think the core idea of what we look at as the metaverse should ultimately be not just a whole bunch of different servers running like the web servers do around the world, which have no relationship to each other. The metaverse should have the potential of being one continuous, seamless environment in which everybody participates and any code, any object, anywhere, could potentially interact with any other object anywhere else. And to keep performance in check, you just have to optimize code using certain patterns. And in that view of the metaverse, you really want the servers that are contributing to the world simulation, whether they're in one data center now or distributed or decentralized, in the future, you want all of the servers to be negotiating a single coherent world state as they go. And that implies all of the game logic running on the servers to produce kind of a definitive world state. But now, of course, that actually sucks for practical gameplay because you have 80 to 100 milliseconds of lag from client to server in a lot of cases. And you really can't tolerate that amount of latency in character movement. And so what everybody has been doing-- John Carmack pioneered it with Quake World in 1996? Unreal Engine implemented it in 1998. All game engines have been running a predictive-- predictor-corrector model, where the server is running the definitive version of the world state, but then clients are running some local copies of that in order to predict ahead what the next state of the world will be so that you can hide all local latency and player movement and simulation of vehicles. And the server is correcting that. So sometimes, you see some jittering in objects. Well, that's when the client is making a prediction, and then the server is coming in and correcting it later on. But the way this has been done in Unreal Engine 1 through 5 has been fairly ad hoc. We expose some functions with explicit declaration, saying, this code runs on the client, this code runs on the server. And you write your code very, very carefully to make sure all of those functions are running in the right place and are negotiating the world state. This is something we really want to automate in the future so that you have one definitive code base. And from the programmer's point of view, the programmer ought to be agnostic on where the code is running. But code is contributing or receiving player input or other local things ought to be predicted locally on the client side-- and then corrected by the server side. And rather than this being done manually by programmers writing specifications, the language runtime ought to handle this automatically. That's the vision. We hope that we can implement this. Not everybody is convinced. But for the right now, for UEFN, this current version of it, it's Epic-written code running on the client and then user written code running on the server. And if we want something to be predicted really well on the client side, then Epic, at the moment, has to write that. Because it turns out it takes a lot more rigor to get a scripting language that can be trusted to run on the client side. You have all of the security considerations of JavaScript and the web browser, plus additional console considerations. So we want to get there. But we're at least a year away, perhaps quite a bit more. AUDIENCE: Thank you. AUDIENCE: Yeah, so I really like everything I've seen. One thing that hasn't really come up in conversations is memory. I assume that Verse is garbage collected given that it runs on Blueprint VM now, et cetera. It's a functional logic programming language. Are there any concerns about space leaks or GC pauses being a performance issue in the future? And have you-- no one's mentioned Rust, but I'm going to mention it now. Have you looked at other memory models that are maybe more inspired by a Rust ownership model or something else? PHIL PIZLO: Sure. So in terms of space leaks, even the ownership model wouldn't help you there. AUDIENCE: True. PHIL PIZLO: If you allocate too much stuff, that's on you. In terms of GC pauses, that's an engineering problem. And so I think that that's how we're going to approach it rather than moving the burden on the programmer the way that Rust does. AUDIENCE: Yeah. TIM SWEENEY: That's right. Right now, there's a garbage collector that will run from time to time. And it might cause hitches. That's the current version of it. But this is a problem we'll be solving more and more over time as we implement the new VM. And the aim of Verse is to just let programmers write as simple code as possible to solve their problem. We don't want programmers to have to worry about memory, ownership, annotations as they write code. It's just another thing that's not all that critical if the compiler and runtime can solve that problem for you. AUDIENCE: OK. First off, this was really interesting. It's a really interesting project. Is "set" a transaction when you're setting a variable? PHIL PIZLO: Set itself is not a transaction. It's just one operation within a larger transaction. The way to think about the transaction scope in Verse is you're always in a transaction until you suspend. So like in the example where you called wait for input, if that thing actually waits for input, that's a transaction commit followed by a new transaction starting after the input comes in. But if you just write a bunch of code that doesn't have any suspensions in it, that's all within a single transaction and completely atomic. AUDIENCE: Oh, OK. So that makes sense. So that means that transaction-- all of the state changes within that transaction, when they propagate to all of the other people that are sharing the same state-- PHIL PIZLO: Yeah. All or nothing. TIM SWEENEY: Every actor tick basically is its own transaction. So there's no concurrency yet. But in the future, every actor tick could try to run in parallel. And when a bunch of actor ticks don't have any read/write conflicts, as detected dynamically, they could all commit. And when some have conflicts, then some would have to be aborted and retried. And that's the whole idea of transactions. But when you have one actor updated, and it talks to another actor, and that collides with a third actor you could have a pretty large chain of events happening all in a single transaction scope. AUDIENCE: OK. Thank you. Second question-- functions, first class, yes? PHIL PIZLO: Yes, mostly, right now. AUDIENCE: All right. Thank you very much. PHIL PIZLO: And this is the last question. Sorry. Go ahead. AUDIENCE: Hearing about all of this, it sounds really cool. And it reminds me of UnrealScript back in the day, which, if I am remembering and understanding correctly, was ultimately deprecated because it was such a big task to keep it updated and keep it up to date. And there was C++, which had kind of solved a lot of the problems already. So what kind of new problems is Verse trying to solve that isn't already being solved by another language? I have some ideas based on listening, but I just would be interested to hear what you guys consider the new problems that aren't already solved. TIM SWEENEY: When we moved from Unreal Engine 3 to UE4, we made a really hard decision to get rid of UnrealScript. We realized that in order to keep up with the expectations of modern languages like generic types and all of these other features that were popular in C++ and growing into C#, you need a world-class language design and implementation and research team. And we had one guy. [LAUGHS] And so that just wasn't a possibility. And so falling back to C++ was kind of the natural thing to do. And it worked just fine for AAA developers, but was not a great outcome for indie devs who found it just hard, or harder than writing in a scripting language. The solution in the Verse era is a language that really advances the state of the art in a number of areas-- with logic programming, with this work on transactions, and with other aspects of our programming model that we think's more appropriate for the metaverse. And thanks to Fortnite's success, we were able to assemble a world-class language implementation and design and research team. And we have that here in the halls of Epic. And we have collaborators all throughout academia who are committed to contributing to making this work. So we feel we have everything we need now to make a really successful go of it. And we think this is a good thing to do. It would be very unfortunate if the move to the metaverse left us with a bunch of rather messy, untyped, nonconcurrent programming languages as the foundation of it. PHIL PIZLO: And-- TIM SWEENEY: One more? Last guy in line? PHIL PIZLO: I think we have to wrap up now. So but we can continue conversations in the lobby or the show floor. Thank you, everybody. TIM SWEENEY: Thanks. [APPLAUSE]
Info
Channel: Unreal Engine
Views: 54,037
Rating: undefined out of 5
Keywords: Unreal Engine, Epic Games, UE4, Unreal, Game Engine, Game Dev, Game Development, Verse, Programming Language, Unreal Editor for Fortnite, UEFN, GDC 2023, Fortnite, Metaverse, Virtual Worlds
Id: 5prkKOIilJg
Channel Id: undefined
Length: 74min 18sec (4458 seconds)
Published: Mon Apr 24 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.