00:00:00 - SLIDES 1 & 2 - IntroductionDoug Binks - So, my name's Doug Binks. I recently re-joined the independent games development movement after 12 years working on large scale projects - with a number of people in this room actually - and it was with Crytek, when I was running the CryEngine department that I met Matthew. Matthew Jack is a senior AI programmer who was working with us then, and is currently a AI consultant working with his own company, MoonCollider.
Now over the years of experience of programming that we both had, we realised, during a discussion, that we encountered a common problem. And that was that, when you're working on a large scale project, and you're writing your code in C++, you have to go through quite a long and lengthy "compile, link, and run the code" process to get to the point where you can actually look at the changes you've made, and then you find it's wrong, and then you have to go back through it again.
There are a number of solutions to this. People have looked at using scripting. but we found that that had its problems.
00:01:08 - SLIDE 3 - ScriptsBut scripting can be useful, programmers use it for a number of things: it's great for rapid iteration; no compile time; no link time. Can be changed at runtime, if you build your infrastructure correctly. And of course there's a degree of error protection because you can't use pointers, access your memory, and additionally you can ensure that the script can't get access to the file system or do the OS calls that might be dangerous.
00:01:33 - SLIDE 4 - Scripting PitfallsBut of course, there are potential problems:
- There's a comprehension barrier. Many people, when I say that, say "well, surely any programmer can program in any other language". But let's say it's 3am in the morning and you've got a graphics programmer who suddenly finds there's a bug. Only, the bug is in LUA code. And that LUA code is behind a virtual machine. They don't know how to access it, what tools to use, that is if you do have tools for debugging in LUA,and they can be stuck. Admittedly if you have a game programmer who can program in LUA they'll be familiar with it. But many of the other programmers won't be.
- There's a debugging barrier. As I said, LUA is behind a virtual machine. There are some tools that allow you to see in between your C++ code and your LUA or your other code. But there's still an issue in terms of being able to access it properly, in the same way as you would do with C++ code.
- Performance is an issue. We all know that scripting languages are inherently slower even in just time compile, than a truly compiled language. After all that's why operating systems and most of the other high performance things are written in C and C++. And on consoles, data execution prevention detection prevents you from being able to do just in time compilations because you can't compile into a data section, and then run that data section. This is done to provide some level of control so people can't hack consoles, also it does happen of course.
- And garbage collection can be an extreme performance penalty. I know of a game that had many tens of milliseconds, per frame, of garbage collection, until they were able to optimise that down. But we were still talking 2 to 3 ms per frame, every frame, of garbage collection. That's a lengthy amount of time. And most scripting languages have no multithreading, or the support for multithreading is not easy and does not cooperate well with the multithreading that might be in your C++ game engine.
- There's a development overhead: you have to write your interface to the script. And admittedly you might find that you can do that in a reasonably fast way using a number of binding mechanisms, but it still takes some time to expose your game engine to the scripting language.
- And finally, given that I've spent a lot of time working with Intel, working with games programmers to make their games faster, using a variety of tools that were available to us. This issue of tools, I noticed was a huge one for use of scripts.
00:04:15 - SLIDE 5 - Could we just use C++?So we thought to ourselves: if we have all these issues with these other mechanisms for rapid development. Could we just use C++? I'm going to hand over to Matthew now, who's going to show us how.
00:04:28 - LIVE DEMO - PulseMatthew Jack - Hi, so to demonstrate this, I'm going to show you a demo which we call "Pulse", and it's a little model of an immune system. So we have a bunch of red blood cells to begin with. Now, what I want to put to you is... have you ever wanted, while you're playing around with your game, to just go in and change your C++ code? So for instance to overwrite the colour here and set them all to be white, and maybe just see that reflected instantly in your game? I think this would be very useful. So how do we go about doing this?
00:05:20 - SLIDE 6 - Edit and ContinueSo one way that you might do it is using Edit and Continue. Probably lots of you have tried this. It's basically a Visual Studio feature. It allows you to change your code, and then it patches in those changes to the running binary. This is great but it has some fundamental limitations.
First of all, it doesn't allow you to change memory layout, so adding a member variable for instance is right out. But in practice, it's also very unreliable. On a big real codebase, you find there are many files or functions where, when you try to make changes with Edit and Continue, it just fails silently. It doesn't give any explanation as to why.
On top of that there's no real error recovery. You make your small change, you introduce a null pointer bug or something and as soon as you hit that, then you're stuck and you just have to restart the application in most cases. So this is a really great bonus for productivity, when it works.
00:06:26 - SLIDE 7 - Dynamic LibrariesSo, another way that we might approach bringing in new code, is by using dynamic libraries. There is of course no limitations to what you can compile to a DLL and of course they can be linked at runtime. So why not compile these at runtime as well? Now one way, that's simple in principle, you might do this, is to take your large codebase and split it up into lots of small modules, perhaps you know, your physics system, your AI system, but really you probably want to go much smaller than that: we know that those individual modules can take a long time to compile.
So if you do split it right down like that, then you might be able to unload a module, change it, recompile it and load it back in. And you can do that with Visual Studio, just about. But changing the codebase to do that would be a mammoth task, and the maintenance overhead as well... reinitialising those modules and everything cleanly, would be pretty prohibitive. So what we asked was, could we automatically compile just a smallest unit, a single source file, and bring that in using dll's?
00:07:39 - SLIDE 8 - DetailsAnd that's what we do with Runtime Compiled C++ (RCC++). So to give you a little more details: when we start up the application, it can be just a simple EXE. The DLLs that we're going to be using aren't present, that is, they're not there at the beginning. But when we start up that exe, there are classes that we've marked as "runtime modifiable", and those get registered, and in doing that we monitor their actual source files on disc. We've got a process watching those. And when those source files change, we break those changes out into mini DLLs, tiny DLLs containing just those changes. So we compile those out, and we use that, use your existing compiler, basically just as a command line process call, which means you can use your existing compiler and in principle it's easy for us to switch to different compilers and different architectures.
00:08:38 - SLIDE 9 - serious changes LIVE DEMOSo let's see that with some more serious changes. First of all let's bring back their colour... and then, what I'm going to do is, whereas right now they're just flat up against the camera, I'd like to give them a random axis of rotation and have them rotate around that in 3D. Now, in order to do that, I'm going to need to bring in this new member variable, the rotation axis. I've got some serialisation code for it I'm going to add in, and... (bring this out of the way...) every frame I'm going to need to update their rotation... and got some initialisation code, a new member function for setting that rotation, and the actual member variable itself which as Isay Edit and Continue can't handle. So we then save that out, everything sets up...
[10:05] Now, of course, when you're making those changes, in reality it would be pretty easy to bring in some kind of an error. If I were to do that, then first of all it lets us know something didn't compile, and actually... in the output window in Visual Studio we can double click on that error, and it will take us to the appropriate line. So we keep, basically, the ordinary workflow.
00:10:40 - SLIDE 10 - More DetailsSo a few more details about how we do this: each of these runtime modifiable objects, we automatically create a constructor for it, basically an object factory. And when we break those files out into these mini DLLs, those new versions of the constructors, when they're initialised, we bring them in. What we need to do is to create new versions of the objects for our old ones. If we're serializing then we need to serialize across the state, and then we can delete the old objects. Now, one other thing that we need to do is to use virtual functions for dynamically binding these objects. If we did any kind of static binding, then obviously the old code would still call the old versions. We'll talk a bit more about the virtual function aspect later.
00:11:35 - SLIDE 11 - Can we Prevent Crashes?Now, this gives us the ability to change our code at will, but we thought that wouldn't be terribly practical if a simple error would crash a whole application. Wee want people to be free and easy about making changes.
00:11:53 - SLIDE 12 - Crash ProtectionSo, we looked at different methods for protecting against crashes. One we looked at was using separate processes. So this is for instance how Google Chrome does it: each individual tab running in its own process. That's great, but if we were running our modifiable code in a kind of sandbox process, we'd probably end up with an awful lot of inter-process calls back and forth, which for games would be a pretty prohibitive overhead.
So instead we looked at structured exception handling. With structured exceptions - they're not the same as C++ exceptions. They're basically an operating system feature which means that if a crash happens, then you can catch it like you would an exception. But they're not C++ exceptions so for instance they're perfectly compatible with the XBox 360. So that's what we do: we catch the crashes.
00:12:50 - SLIDE 13 - I get knocked down But I get up again... and I'll show you that in practice:
00:12:55 - LIVE DEMOIn this is little bit of the update code of our game object we fetch "Behavior" and then we're going to try and update it. So, what would happen if we were to end up setting that to null? Well, it crashes. And we see that this is a standard call stack, with all the normal debugging facilities. So we can see exactly where it's gone wrong.
What's different here, is that if we then hit "Continue", usually we just see the same crash again. But here, our application carries on. We can actually select these objects. They're not updating, because the update code is broken. But our application's carried on running, which means that we can then go and fix the error, save that out, and they set off again.
00:14:15 - SLIDE 14 - FilteringPart of how we achieve that is using SEH filters. The first time that we see this crash, we, in our filter say "ok that's fine", we just pass it through; which means it goes through to the IDE, and it appears as a normal crash. But then when you get "Continue",and it goes though game, this time we do catch it, and we mark this code as broken, and then we just continue. We don't call this update code any further.
00:14:50 - SLIDE 15 - Recovery OptionsWe've got some different options of how we then recover. Obviously we need to stop updating that broken code. But we can keep everything else running, as you've seen. So in principle, you could be running different types of objects: you could keep all the other types of object in the world running, or you might go as far as just stopping your individual instances that are broken.
Your need to wait until some new code comes in, and once it does, you need to return everything to a good known state. What we do is we just serialise in again but you might take that serialisation information from a checkpoint, you might just use the default initialisation of your object - which in many cases would be just fine - or you might reset everything to the start of your level. So there are lots of ways you might handle that.
00:15:42 - SLIDE 16 - Novel TechniquesNow, as well as RCC++ speeding up our existing workflow, there's a few different ways that we can approach things with this technique.
00:15:54 - SLIDE 17 - SnippetsOne of them, we call "Snippets". This is basically where you take one or two lines of C++ code and you drop them in to a template, or something like this. You compile them and run them, quite possibly as just a one-shot. So what could you do with that?
00:16:15 - SLIDE 18 - Interactive consoleOne thing is a really simple, really powerful interactive console.
00:16:20 - SLIDE 19 - Pulse
In this example we can for instance list the available game objects. It's just printing out names of each of the game objects. Another thing we might do is pick one of them and set its colour to white. There we go. Another thing, we might move it around in the world.
16:20 - LIVE DEMO - Pulse
What's happening with each of these is, this is just simple text being wrapped in that template, saved out and compiled. There's no interpreting going on, there's no complex interface that's built for it, it's just accessing the interfaces straight off. There's very little work to be done to get it going. And of course we've still got that level of crash protection so if we fetch something that doesn't exist, try to access its null pointer, it just says "Console tried to read from null pointer".
So you could give this to game designers without fear of them crashing the app, and you could restrict what goes into the interfaces to make sure that you can have control over what they've got access to and what they haven't.
For the next part, I'm going to show you the rest of our game. Now, we've also got these viruses: these little yellow things that are attacking the red blood cells. When they do that they turn green, they turn into infected cells. And these white things are the antibody, the immune system cells. What you see is that the red blood cells are just standing around like cattle. So, how could we improve that?
00:18:28 - SLIDE 20 - AI
Well, a couple of new AI techniques, or rather, a new take on old AI techniques: I'm sure all of you will have heard of behaviour trees. The model I'm using here is a first generation behaviour tree, so that's a simple decision tree with conditions at each of the nodes, and at the leaf of the tree, you select a particular behaviour. So this is very similar to a system I've used at Crytek for instance. And in order to make those decisions at each of the conditionals, we read from a blackboard which is basically just a bag of state for this particular agent. Now how might we implement that with RCC++?
18:31 - SLIDE 21 - Behaviour Trees...
00:19:09 - SLIDE 22 - Soft-Coded?This is my implementation, it's basically just a hard-coded set of "if else" clauses, but, now we can change that code whenever we want. And if we introduce a crash bug somehow, we know that we can handle that, it's not a problem. So why not do it this way? Simple, programmers are very familiar with it, and we don't have to build that whole virtual machine system for a start, and of course it being C++, it's high performance.
00:19:45 - SLIDE 23 - BlackboardsSo how about the blackboards? In Python or LUA, you've probably used tables. They're a really natural representation of key-value pairs. In C++, in this fashion, I think a struct is a very natural representation. Now that we can change that struct and any files which depend on the struct are automatically recompiled - we've got a basic dependency system in there - so we can add members to it and changes do work.
00:20:11 - SLIDE 24 - Learning FastSo let's try applying those techniques
00:20:15 - LIVE DEMO - PulseTo do that we're going to need to do things like adding some perception code, so that we can "see" the viruses as they're approaching. We need to bring in an entire new behaviour, an "evade" behaviour class. We need to add a branch to the behaviour tree so that we select this behaviour when there are dangerous objects around. We need to make a couple of changes to the behaviour tree to be aware of this new behaviour code, and in the blackboard we need to bring in this new member variable to the struct, which keeps track of the dangerous objects, and a bit of serialisation code. So if we do all that, save it out, you can see the red blood cells starting to move away.
So we brought in a whole new behaviour, changed our behaviour tree, changed our blackboards, all in C++ while it's running. OK, so I’m going to hand back over to Doug.
00:21:43 - SLIDE 25 - Practical Application
Doug Binks -
So actually I'm not sure whether you noticed but he left the demo running throughout all of that, which I think is pretty cool in and of itself.
21:50 - SLIDE 26 - Optimizations 1/2
Now, you noticed that we mention virtual functions, and I would probably have rolled my eyes if I'd heard that: I'm not very happy with virtual functions in many contexts especially on PS3. So we might think, ok, we need to optimise that. There's a simple way to optimise it: one of them is that you can remove the virtual functions. They're not necessary if you don't use polymorphism in the rest of your code base. So you can have a simple macro that defines the virtual function as being a virtual function when it is in RCC++ during the development process, and then for your final release build, you just define it to be nothing, and this will work.
There is of course a penalty to pay in this in that the final release build now has a very different code base to the code that you've been using during development. Therefore you'll need to ensure that you're aware of that and you're going to take the hit on your testing and your debugging of that. Also it's worth noting that you actually need to use this particular class as the interface to your functionality rather than some other abstract interface. So there is an extra level of linking here that does slow down compile time very, very slightly, but we're still in the 1 second, 2 second or less time frame here on those machines, particularly if you have an SSD and a powerful machine.
00:23:15 - SLIDE 27 - Optimizations 2/2There is another optimisation technique which I think is really the way that we should be going, and that is to start thinking more in terms of data layout. Data oriented design, type that into Google you'll find some good information, I love Mike Acton's Typical C++ bullshit talk that he gave at GDC.
We simply don't think about calling a function on a single object or a single structure. We start thinking about using an array, and splitting those arrays up so that the data access is accessing and going through the least possible data if it can. And what we see here is, I have a virtual function that's calling an execution, or some action that’s going to be performed on one game object, well, why don't we do this over an array of multiple game objects? So in the first case we might have had a hundred to a thousand cycles during the execution, and maybe 10, 20 cycles or even more on the virtual function cost of needing to look up that virtual function in memory in one place then go back to the object memory in another place. And that's amortized if we have a thousand objects in here, all of a sudden we go from a 10% cost per virtual function call to .001% or so.
00:24:27 - SLIDE 28 - Case Study: GraphicsObviously, doing these things in AI etc. is all very interesting, but myself, somebody who's been doing programming in graphics for quite a while, I wanted to try out doing this on some graphics code. The only thing I had available to me at the moment was Dynamic Resolution Rendering, this is a demo I made for Intel showing that you could change the resolution that you're running to on the fly. And I moved the scene rendering over to RCC++. This took me about 4 hours, and now I can completely alter the scene rendering, not just the shaders but also the code, and turnaround times are about 1.5 second. So I'm going to show this now.
00:25:15 DEMO - Dynamic Resolution RenderingWhat I'm going to do is, I don't like the lighting here, it is a bit flat - I have a very basic lighting set up, it wasn't about making the highest quality lighting in this demo - I have the sky that’s blue, so what I'm going to simply do is create a little bit of hemispheric blue lighting from the sky, in addition to the direct light of the sun, so that we can get this arm here, the top part of the arm, I just want to try to catch a bit of the blue on that but none on the rest of the shadowed area on the bottom.
First of all I'm going to alter some shader code. This, obviously, we can do on the fly: shaders can be compiled on the fly. So, I've altered a constant buffer, which is going to throw a warning up in anybody's head who's actually done shader compilation before, because that means we've altered the constant buffer, we needed to set those constants in the C++ code. So I go into the C++ code - I can now edit that - so I can edit the constant buffer so I can add those values in. And now I can go down to the actual code itself, it's going to set it up, and I used a bit of a hack I'm just going to set the unlit model to have a lighting colour of 0 for this particular light, and for the lit models I need to set the direction of that light and I need to set the colour of that light. So this isn't real hemispheric lighting: I'm just going to have a secondary light put in, it's going to be pointing downwards, and it's going to have a small amount of blue. So it's ay axis of minus 1 and about 0.4 for the blue.
So I'm going to just switch over onto a console output now, so that we can see this, and you've probably noticed I've actually compiled is several times to try and get this right. and now if I save it all out, and look over to the main application here, that's going to switch over to a nice light blue on the top. It's a little bit subtle... it's supposed to be subtle... so I'm going to see if I can repeat this section of the video a couple of times so you can see the switch in change there. So I just cut and paste the video, but you can get the same behaviour by actually "ctrl+z" in the code as well.
So that's a fairly simple thing we can do. For me I find that it's a really powerful technique. Graphics is obviously something that is very visual, and getting that visual feedback in response immediately really works wonders.
I’m handing over to Matthew now for another case study.
00:27:33 - SLIDE 29 - Case Study: Recast DemoMatthew Jack - So in my AI consulting/contracting, I've used Recast an awful lot, so this was one that I was keen to apply it to. And for now what we've applied it to is the debug draw, and the GUI itself (of the recast demo). If any of you aren't familiar with it, it's basically an open-source navigation toolkit. The basics of this conversion was done in one day by a colleague of mine, Mike Bell. He hadn't used Recast before, and he hadn't used RCC++ before. Now what we can do with this is adapt the GUI on the fly as you'll see. And we can also change the debug draw, which as an AI programmer I think has some exciting possibilities.
We've had a couple of problems with it. For this code, these interfaces we were affecting, the demo uses kind of C-style APIs static global functions. So they're not wrapped up in an object, which makes it more difficult to make those runtime-modifiable. One thing that you can do is a simple wrapper around those static functions so they call a modifiable object. You could also actually adapt the code so that it's calling through objects, which I think in the long term is the better way to do it if you're happy to make the changes. So let's just have a quick look at that.
00:29:05 - DEMO - RecastThis is Recast, and the first thing we're going to do is these checkboxes on the side here, we want to change their size. We're going to do that in the code: we're just changing a static constant there, and if you watch: change in size. -I'll just bring that back- So instant changes to your C++ GUI.
Now we want to add a couple more items to the menu here, below "Create Agents" so we bring those back in, and they pop up straight away. Now we can select a move target, and using the detour crowd functionality two agents will try to get to the target, we can adjust their separation weight: move them further apart or close together. But we'd like to be able to separate them by more than that, and the slider only goes up to 4. So let's just go and change that, bring it up to 20. And you see the slider now goes all the way, and we can apply that in the running game.
Now the final thing is changing the debug draw. You can see the navigation mesh is divided up into polys, but I often like to see that colour coded so that it's really obvious which poly is which. So we're going to change the code now, to do that. We're going to find the debug draw for the mesh, and we're just going to override the colour to a random one based on the index, and there it is applied.
I think that's very exciting for when you're in the middle of debugging something, you can see there's something complex going on with your AI, and you don't really want to stop everything to add the debug draw to see what's going on, being able to do it on the fly should be very powerful.
00:31:12 - SLIDE 30 - Crytek's SoftCodeDoug Binks - So, you heard this here first, we got approval - which we're really happy about - to be able to talk about the fact that Crytek implemented this. Will Wilson, a friend of ours, and also he was at the first talk we gave last year at the AIGameDev conference and soon after we open-sourced the code. He saw this and he loved the technique and he did his own implementation for the CryEngine.
This is a different implementation in that they decided to go for a tool-driven approach. It's a Visual Studio add-in. This allows you to test this actual application without having to run the game, without having to run the engine, without having to run the editor. We can ensure that all the compilation and everything works fine through Visual Studio itself. It also means that it can pick up on project settings and ensure that the compilation is being done with the same for example if you choose to change your standard library from one to the other, that can be picked up on and used within it easily.
We use a single type library in the example that we give on our open-source runtime code but he's done this in a slightly different way so that you can have user-defined type libraries. This makes it a little more difficult if you want a new type library, but it makes it more flexible. And also to speed up development, rather than use a serialisation function thats called per instance there’s a simple macro that he's using for member exposure. Additionally he's added an extra functionality, which is the ability to expose global functions through an API an SC_API macro.
So this works in the CryEngine. They've been using this now for a year and a bit, and it's been used on the end of Crysis 2, and on a game in development, Ryze, for the AI and for GUI in particular, but also for other parts of the code, and of course on the CryEngine for Crysis 3.
00:33:08 - SLIDE 31 - Unreal Engine 4 Hot ReloadMany of you have seen that there is a recent video of Unreal Engine 4 and also the Unreal Engine 4 website has some details that showed, towards the end of this video, that you could click on an object, see the functions that were exposed by this object, and then go to that in the source code, change the C++ source code, and see this reflected in the game.
This seems extremely similar to what we're doing in RCC++. I haven't been able to get an official comment from anybody and Mark's not in the room, so I can't ask, but we do believe it's using a very similar technique, and the compilation times appear to be pretty much identical to what we're seeing. They’ve added an extra feature in, in that you can see the functions in the editor, that are exposed by that object, which I think is just a fairly trivial thing to do using a line and file macros.
00:34:00 - SLIDE 32: Related WorkAnd there's some related work that we've seen as well. One in particular is from CERN. There is a video from a Google Zurich talk online if you do a search for this. Cling uses LLVM Clang - Clang is a front-end to the compiler and LLVM is the compiler - to produce an interactive C++ interpreter which was designed for the CERN physicists to be able to change their visualisation code on the fly. (This is very interesting to me, I used to be an academic physicist so it's a step beyond the tools that I had 20 years ago).
And also we know that Bitsquid's tools support executable reload. They have a secondary tool that stores the state of the game, then they recompile the entire executable, reload that, and then get the data back from that tool. It's a little bit slower I believe, though I don't know the absolute times in it, but it's a very similar technique in trying to get that iteration going really fast.
00:34:52 - SLIDE 33 - FutureNow, obviously we want to carry this forward in the future, we have - liberally - open-sourced through Zlib license that we have got up on line [on Github]. We want to support more platforms. Now I've gone from big studios to a small studio, so I'm likely to tackle OS X next since I’m developing for PC, OS X and potentially Linux (note that since this talk OS X and Linux support has been added).
We'd also like to improve the ease of integration. I think we've done an enormously good job of making it very simple. As you saw, it takes a number of hours for somebody who's got a little bit of experience with using the toolkit to put it into something completely new, and it takes about a day for somebody who hasn't had any experience with either the application your integrating to at all nor the RCC++ technique.
The other thing is to use a separate process for the compiler. For those of you working on consoles, you can't compile on the console. Or if you're working on a handheld, you can potentially compile on Android but on iOS I don't think you can. So a secondary process running on your development machine, communicating over TCP-IP would be the way to go for that.
Finally, I'd think I'd like to improve the serialisation so you don't have to have serialisation in your code. We can do it ourselves with basically taking the source code file, interpreting that in some way - perhaps through LLVM and Clang - and then adding introspection in on the moment you make the change. So we can basically store the old code, see the new code, and then we can decide how to patch those data members up. I think that would be pretty sexy.
00:36:21 - SLIDE 34 - ConclusionIn conclusion, just so we can give you some time to ask some questions, really I think we have done the job that we set out to do and more. We set out to get rapid iterative development so that we could replace scripting for programmers, and I think we've done more than that. I think that we can edit graphics and AI code and all sorts of other things that we didn't initially think would be that practical.
We've done it in one language, so you're in C++ or, if you wanted to make this into whatever compiled language you want then go ahead, I think it's quite reasonable to do so. It's in one toolchain and your interface to your engine can be simplified enormously, and it's obviously got the full high performance potential that you have when using a compiled language: C or C++, or even putting some assembly there, you can do anything you want with intrinsics, multithreading, it's great.
00:37:08 - SLIDE 35 - Rapid Development with Runtime-Compiled C++There is an open-source prototype available and you can find that either by doing a quick search for it, apparently if you search for "compiled C++" we're about 8th down the list on Google at the moment - which is great - but our blog is at runtimecompiledcplusplus.blogspot.com, and obviously follow us on Twitter @dougbinks and @MatthewTJack or the hashtag #RCCpp.
Thanks everybody, anyone has any questions?
00:37:40 - QUESTION - So when you flag code is broken, how much are you skipping at that state?Answer - Doug Binks - You can actually skip pretty much however much you want. In our demo, what we did was we wrapped the... we have an update function that's called on all of the objects that support the updatable interface - apologies for those who don't like C++ polymorphism - and so basically we skipped all of the updates for the, what we call, game objects. That actually included a couple of graphical user interface elements that could have been exposed elsewhere. But you can do it on as much code as you want, you can even do it down to the level of the very function call that had an error and stop calling that function call itself, and then all the rest of your code can carry on. It's up to you. We provide a kind of framework that you can use, but you can use it at the level of granularity that you want. There's a simple wrapper that you put around a function that you call just to protect it and to catch the errors, and prevent it from being called again until you’ve got new code.
00:38:50 - CREDITS
- Matthew Jack email@example.com
- Doug Binks firstname.lastname@example.org
- Special thanks to
Transcript by Juliette Foucaut