GASP---It-s-Mover!-Game-Animation-Sample

https://m.youtube.com/watch?v=i27eY7LbRzc

Frame at 0.00s

Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Hello, everyone, and welcome back to Inside Unreal, a show where we learn, explore, and celebrate everything Unreal. I'm your host, Tina, and today we're going to be digging into some of the updates that have come across for the Game Animation Sample Project. Or as the wonderful, incredible title that I wish I could take credit for, but I can't, gasp, it's Mover. A quick news thing for today, and then we'll get into the topic at hand because there's a lot to cover. coming next week to our YouTube channel there's going to be a behind the scenes look at the lost chapter Yuki's Revenge this is a lost Kill Bill scene reimagined in Fortnite with Unreal Engine directed by Tarantino himself and starring Uma Thurman so if you don't want to miss this cinematic world that's getting brought to life be sure to tune in next week so keep an eye out for that but otherwise we'll get into all of the cool stuff that's happening now. So let's go ahead and get our wonderful guests for today introduced. Caleb, we're starting with you. I've decided. Okay. Would you like to tell us a little bit about yourself? Yeah, I'm Caleb and I'm a technical designer in animation on the product team at Epic. And for the past couple years, I've been involved in a lot of different things at Epic, some special projects, miscellaneous stuff, really. But most notably, I've been... Myself and the team has been working really hard to bring this project to light, which, you know, it is the Game Animation Sample Project. And, yeah, that's kind of my focus now, is to continue to improve that as time goes on. And I'm really excited to, yeah, dive into it. But that's me. So moving on. Fantastic. Thank you for being here. Appreciate you having the time. Next up we have Jack Would you like to tell us a little bit about yourself as well Sure Hi Tina Yeah so I Jack I a gameplay animation programmer here at Epic I relatively new here so I been here about a year On the gameplay animation team, we obviously work on GASP and work at the intersection of a lot of different teams that need to plug into animation. So yeah, I'm looking forward to sharing what we've been working on. yeah and I'm looking forward to having you here today for this evening so thank you for being here next we have Dustin do you mind telling us a little bit about yourself as well hi I'm Dustin I'm a senior technical animator at Epic I've been here about a little over a year just like Jack I work on the tech dev rel team so I'm on the other side of like EPS and other support services and visiting studios that help them out. And I had an awesome opportunity to come over and help this team out and help out on GASP with this release. Awesome. Wonderful to have you here. Thank you for joining us. Next we have Justin. Want to tell us a little bit about yourself as well? Yeah, hi. Justin Hare. I'm a senior engine programmer over on the gameplay systems team. So we're kind of of a sibling team to where Caleb and Jack work on. My focus has been, for the past few years, character movement, replicated movement, making things network together, and then hopefully making your characters look nice, replicate nice, and plug in nicely to all the other systems, whether it's animation, as we're going to talk about today. But there's also physics and performance networking, all the stuff. So I get to drink from multiple fire hoses. It's a blast. And this project is actually kind of special to me. Caleb and I have been talking about getting our work together for seems like years, doesn't it? Yeah. They've had ideas about taking character animation network sort of beyond what was possible. And yeah, so at the same time, we were building this new mover system. And finally, we've got something to really show for it. And that's what we're going to be talking about today. That's so exciting. Thank you so much for taking the time to be here. And then last, but certainly not least, we have Tony. Would you like to tell us a little bit about yourself as well? Yeah, I'm glad, Tina, that you got the memo that I always go last. So yeah, hi, my name is Tony Giardini. I am the animator on the product team. And anytime you see something moving or moving poorly or moving well, I had some sort of hand in it or got yelled at for Caleb for not doing it right. So I've been here at Epic for almost... That's not true at all. Caleb is actually very nice. He accuses me of being a terrible person. Yeah, I do not. I just deflect because I'm a terrible person. So I try to drag you down to my level. uh so yeah i've been at epic for almost four years now uh and pretty much on the product team at any time any of the teams need help with gameplay things things not working things that need to work better or just need to tap into my knowledge of all the things that i've done before six times before then uh i can i can tell them how to do it or help them do it uh so yeah that's me fantastic well thank you all again for being here and i know there's a lot to get into so i won't take up too much time i think caleb i'll just hand it off to you if we want to dig into what we got today let's do it so i guess you can take my screen and wait to see i guess we're good there we go so there's a lot that went into this update um lots of it is underneath the hood uh so So there are a couple of new features or gameplay features that we've added. But a lot is really sort of more technical, foundational. And we're going to start by, I'm just going to show off kind of the new features, starting with the new Mover character. And then we're going to get into a breakdown of everything later on. So we're probably going to start and end the stream with Mover. But it's just going to be super high level at the beginning. So first things first, this is sort of the default level. The most important thing that you should do when you start playing in Pi is stand on this button right here, and that's going to open up the game animation widget, which is kind of like our project's control panel. I always tend to just dock it right there. And it gives you access to a lot of different console commands that you can execute here just with some buttons. and this is just how we like to work. And as you can see, down here, we have a Pawn Override category and we have a new character. Now, this is actually a Pawn class, not a character blueprint. And this class uses the new Mover component. So if we click on that, we have a new character that's running around. And right off the bat, you might see that the animations are also a little bit different than the other character. That's because as a part of this new Mover Pawn, we really wanted to kind of put Mover through its paces and get different kinds of trajectories and different kinds of motions. And so to that, we felt that we needed to build a whole other animation set. And so, Tony, do you just want to briefly talk about kind of why and what we did? Sure. The original motion matching character that we had in 5.6 and before was a like just full motion matched character. And in this one, we were kind of going back to a slower, more deliberate motion. The previous motions was more kind of like twitchy and for a shooter had very rapid transitions between the animations. And so you kind of actually need a lot more animation in that case because you now need to support all of these like four frame blends into new motions. so this one is kind of a hybrid, more of a slower deliberate set but still within a far wider breadth of games that it could work for. Having the super fast set, it kind of really limits the amount of games it can be used for because if you're tearing through the content at 5 meters a second you just through the level so it was more kind of shooter based like Twitch shooter But now it can work for pretty much a lot more games and it allowed us to kind of have more weighty transitions but then also kind of like showed the difference between like a motion-matching animation, a state graph animation, and all the animations support any of those. You can kind of trim them down, rework them. It'll work for any of those. You can have it as a state machine. You can have it as motion-matching. the animation support all of that and that was kind of like the the point for it and we went back and they're all new so they're not just reworked versions of the previous they are all new animations all to the correct capsule we did the same way as we did before where it's the exported capsule motion that has now had the animation just on top of it so it's one-to-one for like your root motion is your capsule motion is your everything so it can you can show that you can have something root motion driven you can have something capsule driven and you can see them against each other and it will be like millimeters off versus being completely different. So, yeah. So to sum up... Oh, sorry. To sum up, we're calling this the relaxed set because this is an animation set that we just simply feel is going to work for a larger variety of games and game styles like action adventure, those sorts of things. Now, with the mover characters, something that we really put a lot of effort into was rotation. I've fought personally with rotation in Unreal for a very long time. And so I'm going to enable some debug draws so you can start to see kind of the stuff that's going on here. But if I enter into strafe mode, which is I do that by middle mouse with keyboard and then the right thumbstick on the gamepad, I can enter into a mode where the character is always trying to look toward the camera direction. But you can see if you look at the debug draws, there's a lot of fancy stuff going on here. And we're going to break down what's going on in more detail later on. But essentially, we've got some different zones that we can determine that we're in based on input direction. And then based on input direction, rotate the mover pawn into essentially any arbitrary angle. And that allows us to have a really fun approach to strafe locomotion using what we're calling spin transitions, where the spin transitions are taking us in and out of essentially running forward and running backward. And this also works very well with walks. So you can see I have some nice, really smooth transitions in and out of my forward and backward directions. And we also, so over here in the widget, we have a little bit of configurability here. We have two different dropdowns, strafe style and aim style. And these are just console variables that we've added to the project. But when I change those, you can see that the quadrants or the zones and the debug draws are different. So now let's say I want to actually play strafing animations when I'm moving left and right. I can set the strafe style to use all the forward, all the directions, the forward, backward, and left and right. And so now we can get sort of what we had before, which is some four directional strafe. And then we can even take it, you know, so we can reduce it down to the forward and backward directions. That's what I was showing off. We can go even further and get what's kind of like sort of Max Payne style, where you're running forward, but toward the camera. and then when you cross that threshold, you do 360 spins, which I think is really, really cool. And then so to sort of like further stress the system, I added a kind of a simple twin stick mode where the, and I can just turn on the controller debug here so you can see what's going on, where the right thumb stick actually controls the orientation intent of the pawn. Now, a lot of people might think like, well, what's the big deal about this? Well, the really big deal about this is in contrast to CMC, Mover allows you to do basically whatever you want to the way that the character moves. In CMC, which is the character movement component, you basically had two options for rotation. You could rotate toward the control rotation or you could rotate toward the input direction. But now Mover completely allows full freedom and full flexibility to do whatever you want. And so I find that very important when building different kinds of games and game styles. And then also to further show this off, I run over here into this zone. We have a very simple target lock system where the character's orientation intent will rotate toward that little thing in the middle, I guess, I don't know, a pin, when I'm in that zone and then sort of automatically rotate back toward whatever rotation style I'm in. So yeah, that just gives a lot of really interesting control that you have over the character, and then we've worked hard with those spin transitions to make those things seamless. Another thing that we've done with the mover pawn is we've added a slide mode that you can activate when you're sprinting if you hit the crouch button. So if I'm sprinting and then hit crouch, I can go into a slide. And the neat part about this is Mover offers blueprint extensibility to movement modes. And so we actually have a blueprint extended movement mode that's sort of a modification of the walking mode with lower friction and different deceleration values so that we can sort of get a really nice sliding mechanic. And we've added a slope up here to sort of demo that. So if I slide, I'm actually speeding up as I'm going down and then slowing down as the slope angle gets more shallow. Some other fun things that we have, like some really nice debug draws, courtesy of the Daniel Holden, if you know who that is. He did a lot of work on this project, so I just want to give credit where credit was due. Debug draws are one of those things that he did, and I think they're really, really cool. they can show off the speed of the character, some curves that we have here, etc. So anyway, I think that's mainly it for new features. Oh, the other thing that I should show off, though, is because of Mover, we get very, very good replication pretty much out of the box. So let me over here and turn off these shapes here. Oh, where did it go? Hold on. OK Windows 11 come on There we go So yeah, with Mover, we get pretty much automatic replication. We're going to dive into that later. And so you can see that all those cool strafe spin transitions are working, networked, without really any additional work. so that's I think that's it someone correct me if I'm wrong in terms of sort of the main features on this moon mover character is there anything else for this I think you got it all you're good you're good so with that I'm going to pass it over to oh wait no I didn't get it all we're wrong because there is oh no another thing that I wanted to show which is the new foot placement stuff. And Jack's going to dive into that later on. But I wanted to demo that if Unreal could let me because it's freezing right now. It's thinking about it. It's debating. Wouldn't it be an Unreal live stream without crashes and freezes, right? No. It really wants Jack to talk about it. Come on, come on. Do something here. All right. Well, it's frozen. I'm good to go, man, if you want to switch to my screen. Yeah, okay. So go for it. I mean, we, oh, there we go. I crashed. I'll get this back up and running soon. But I'll talk briefly about what we did or why we did it. So the new mover character has a different movement component. And the anim node version of foot placement relies on information from the CMC. And so in order to get proper foot placement, we had to come up with a different method. and we felt that Control Rig would be a great way to go and so we have a whole new foot placement mode or foot placement system that Jack made in Control Rig for the characters. Yeah, I was going to pass it over to Dustin actually to talk about the NPC stuff but Jack, if you just want to Yeah, that's it. We'll get into it in depth later. I can go through the Control Rig but it's As you said, it's basically going to do the same thing that those anim nodes were doing. But we, you know, since we're using Mover, we wanted to invest in a control rig solution because we love control rig here and we think it's really flexible. And it's also going to open up procedural animation to people that can't code. So I think it's pretty cool. So I won't add too many spoilers, but we'll get into it later. Sweet. So yeah, then the other massive addition that we've had to this project is sort of the introduction of NPC characters into the sample project. So to talk about that, I'm going to hand it over to Dustin. Yeah, thanks. Go for it. Yeah, so after the Witcher demo that was done, the team kind of reached out to me to see if we could talk about getting some NPCs into Gasp. And one of the first things that we wanted to do was have some AI-driven NPCs that interact with smart objects. So I worked with Fonny, who also just joined Epic. He's not here today, but we partnered up on building a smart object demo where we have a bunch of NPCs here. that they're controlled via State Tree, which is another important element to this. We don't want to, we wanted to show off State Tree. They're a sister system to Behavior Tree, but they're also really generic, so you can use them in a lot of different ways. And one of the other goals that we had with implementing this was to show how you can have AI-driven characters using the GASP animation systems, including motion matching um and there's a lot to tie together it's a little complex and we'll go a little bit deeper in that in just a bit but we have a new level here um it's the npc level you can get to it from the main default level if you want um but there's a little arrow that can take you there but also you can just open it up and when you hit play um here you will get this abp walker error uh we'll deal with that in just a second but um these characters they just look for smart objects and then go and sit down and play through their state trees. And then they will go through and try to locomote to a different spot and then come back and sit down again. All the while, they'll attempt to avoid each other with RBO. And we have a mix and match here of both like mover characters and CMC characters. So we show how you can use these setups in both scenarios as well. Lastly, this is also networked. Networking is a big part of GASP. I think we want to show more and more networked things. And so we set this up to be networked as well. And this is just the start of this. This is relatively straightforward in terms of how it works, but we want to show more and more NPC stuff in the future. So the reason why it's called the NPC level is because this is going to grow in the future. But outside of that, another thing that we wanted to show was Locomotor. So Locomotor is a plugin that was written by Karen Ritchie here and further developed with Helge and the rigging team. And basically what it is, it's a procedural animation system where you can drive motion on characters through control rig. So I'm going to just hit play here and you can kind of see it. I'll go and I will not show you it apparently. I can go into depth a little bit about how it works but basically the teleport no longer exists. Great. We just need to refresh that note and and we're good to go. But with the introduction and teleporter in 5.6, you could kind of control characters walking around. And those were more NPC-driven. We wanted to show a player-driven version here. So we grabbed the mech that we kind of show in a lot of our live demos, and you can Now hook it up to this locomotor and drive it around. So this is me driving this in the world. And there's no animation associated with this. It's all procedural, all done programmatically via Control Rig. And Control Rig is going to be a big part of the future of the way that we do things. We talked about the foot placement stuff, for example. This is just another example of that. So, yeah, that's the high level. Yeah. I was going to deep dive a little bit into the kind of the control ring and the setup of this. Did anybody want to point anything out before I dive into that? No, I think we got that all covered. I mean, again, like I said, you know, not a ton of new gameplay features, but a lot of new foundations, if you will. you know, mover, et cetera. And so it's one thing I should mention is that we still have the CMC pawn in the project or the CMC character, I should say. But going forward, we're going to be putting, I guess, most of our efforts really into the new mover system. And so that character will exist kind of as, you know, legacy. Let's see, is there anything else I want to mention? Oh yeah, I should mention this as well. So the new mover character, If you wanted to share my screen real quick, actually, I should switch levels because I was. So last update or last time that we put out an update, which was 5.5, we added a different style of. Well, it's not motion matching, but it's like kind of a hybrid system that uses state machines and motion matching at BlendStack. And we did a breakdown last live stream we did. For the mover pawn, we decided that that's going to be the default mode. So if you start using the mover pawn and start running around, that's not actually the full motion matching setup. That is the state machine hybrid setup that you're seeing. And the reason we did this was as animators and designers, we felt that we could be a little bit more intentional about the animation. and when it reselects and those sorts of things with that setup. And so moving forward, when we're talking about the future of animation systems in Unreal, like UAF, we're really going to be focused on that kind of a workflow that blends motion matching functionality, but still gives the control of, or still provides the control that state machines and choosers and those sorts of things allow. So the motion matching setup still exists in the project. it came in pretty hot we had a new I don't know if I should say this but like the ex-anime director of arc raiders has joined our team which is really really excited and he took on the motion matching setup which is really cool so that's still in the project but yeah I just wanted to point that out people are confused like you know what's going on in the animation graph yeah anyway so now we can go into the breakdown portion of the project, I think. And so I'm going to send it back to Dustin to talk about the locomotor and MTC stuff. Awesome. Thanks. Yeah. So locomotor is built off of control rig. It is a node that exists in control rig and runs. It's a simulation. So in the project, we have a folder here called locomotor. We kind of sectioned it off. And it just comes with a few things. There's a game mode and a controller just for the playable aspect of it. But then there's kind of three other pieces here. There's the walker itself, and then our control rig and our Anim Blueprint. In 5.7, there was a bug fix that allowed us to be able to drive the control rig through the AnimBP. The AnimBP is pretty straightforward, we minus this teleport thing here. We have in the event graph, we calculate kind of just the camera direction and forward vector to get a look at target, basically. And from there, in the anim graph, we just have the control rig that we point to and that camera aim target. And this is how we kind of swivel the aim of the character. But if we go to the control rig itself, there's a couple steps that we take. This is, this setup is a mirror of a tutorial that Kieran has written to kind of help this up with a little bit of added bits in there. So in our construction events, we've got our, we create like a control for our root. And then we create some controls for the locomotor bones on the feet to kind of attach to. And then during the forward solve, this node is kind of the bulk of the thing that's doing the work here. So this locomotor node has a lot of different options in it. If I minimize it here, it'll kind of show up like this. but as this thing is this mech is really large you kind of need to start setting up and controlling like speed and step and phase lengths and the way this works is if I grab this control here and I move it you can kind of preview what's happening and what the locomotor node is doing is it's kind of trying to simulate and have the character walk towards the root bone here and the way it does that is there's a there's some uh math to kind of like create arcs and phases for the different feet and that's all defined here in this node so uh just some kind of tips uh to i'm not going to super deep dive into like tuning this or anything like that but just some tips uh your phase speed max and min are really really important um and your min step length is really important those things kind of tie together if you move the thing a little bit the mech will try to walk In the case of how I kind of set this up to be driven you can really move like this in the game but I wanted to create kind of like a heavy set robot So when the capsule is moving around like this it tries to reach that capsule in that slow-ish kind of way. The next thing that's important is the foot sets. So this is where we define the different parts of the mech to be driven by the feet. And these are attached to those bones that I created earlier in the construction script of Control Rig. From there is the pelvis setup. And this is kind of the root of how these things attach and relate to each other in the locomotor. So as I move this, you can see how the body kind of settles and moves. That's locomotor doing work in between and that's that procedural anim bit to get that weight in there. And there's some specific tunables. But if I were to disconnect this here in the flow, and I were to animate this, you'll notice that the model doesn't move. But you can see Locomotor kind of debugging and trying to do its work there. The next thing that we do is we just hook it up to a full body IK system. And this full body IK node basically defines the different end effectors for the feet. And then we drive the pelvis kind of separately to have those feet move. So now as I do this, it can drive that around. And you can do this on any type of character, including a iPad or anything like that. So lastly, to just kind of show that it's just a part of a control rig and you can do a lot more things in control rig, you can actually add more functions post locomotor, you can do other part fix ups, it's just modifying the pose as it steps through each function here. And so I've got these two aim notes here to handle the like, turret aim left and right and the pitch of the gun part. And ultimately, what that does is it creates that sense where if I turn the camera, it's trying to aim where I'm aiming at and then the locomotor part is trying to catch up separately. This is a relatively simple setup, but we've got some talks from some folks here. So Karen did a tutorial on EDC that you can follow to kind of set this up. I created a QR code. But also at Unreal Fest Stockholm, Helge did a talk called Make Control Rig Smart. I don't know why it says state tree there. That's my mistake. But basically, he did a talk on this, and it goes into much further depth on how to create some really cool smart control rigs, similar to kind of what Jack is going to be talking about in the future. Cool. I'm going to jump back. So that's kind of Locomotor in a nutshell. I'm going to jump back to the NPC level. are we good to keep going? Yep. Awesome. So kind of jumping back to NPCs and kind of deep diving a little bit into that. At a high level, the characters here are driven by State Tree. And just a little kind of tour of where these things are inside of the project. There's two main folders for the smart object setup. There's the AI folder here, which is more generic AI-oriented things. And then there's the smart object folder here, which is all of the smart object-specific setup. If I go into the AI tree, the main thing that's here is we are using the exact same pawns and actors for our characters. We're not making a new one. So if you're running around in the environment as a player, these are the exact same blueprints. and the only thing that we do to kind of make them AI controlled is we just give them a new controller which is our AI NPC smart object controller here so if we scroll down to I'm just going to type in controller into the search I just redefine the class here and once we've done that they're now AI controlled at that point and we've kind of handled any of the other setup that's needed for that. But the controller itself has our StateTree AI component. And this is a really simple controller, but the main thing that it does is on begin play, it just starts the logic of the StateTree itself. StateTree is generic. I'm not going to do a super deep dive into how to work with State Tree, there's a lot of complexity that you can spend in there. And I'll put up a tutorial written by TechDevRel's James Keeling here in a moment to kind of talk about that. But we wanted to build something simple to kind of introduce folks to it. So in our State Tree for our AI characters, this is it. This is State Tree. State Tree is a hierarchical state machine. So basically what happens is, is it evaluates from top to bottom, but it can jump around depending on the outcome of the different tasks or evaluators that are in each state here. But as for the gasp setup, we have a really simple state tree where basically what it's trying to do is it enters in and tries to use a smart object right away. And if it can't use a smart object, whether it's on cooldown or it can't find one, it goes into a patrol subtree. State tree, in particular, allows you to initiate external state trees as well. So that's kind of what's happening here is if we go into patrol, it launches a linked state tree. So if I double click this we have our other state tree here that just finds a random location and moves to it and then waits And once it succeeds it tries to just go back to launching this state tree Now that a rough overview And there's, again, a lot of features that you can do inside of state tree. But kind of continuing on with the rest of the organization of the project, in the smart object folder, there's a few pieces that we have available to, that we've added to the project to, that you can expand upon. The first one is we have a new component. This component here is a component that exists on our sandbox CMC character and our mover character. And its job is to manage the animation. It's the motor of this whole smart object system. But if we go to the bench folder, we have our actual bench smart objects. And inside of here is the brain of the smart object. And this is another state tree. And the way that smart objects work is this character goes and looks for a state tree, or sorry, a smart object, and it finds it. And then what it does is it says, hey, is there a spot open on this state tree? And you'll notice as I click on this state tree here, there's these different slots and nav points. And if there is a spot open, it will claim that spot and then run the state tree that's defined on that particular slot. for that setup. And in this case, what it does is it basically injects this state tree here to run onto the character that is using that slot. And what's great about it is that you can define this per object. So say this is just a bench and we have animations and things and logic that we want to play here. But if I wanted to hook this up to a vending machine, I could have a completely different set of logic for that. and it'll also set it up so that multiple MVCs don't try to use it or can try to use it if they want to. But in general, it's a way to inject custom logic per object in the world. That is kind of the high level where things kind of are. But to kind of deep dive a little bit into how some of these systems work, we'll go back to our our AI state tree. And we've organized this a little bit differently than I think you would normally do this just for clarity. But what we wanted to do is design some steps through this so that you can kind of see the intended flow. So in this state, we have this cool down and this just prevents AI from kind of re-choosing to sit down immediately. They'll like patrol right after they're done sitting down. So it'll go jump down to this state if that fails. And that's what this little arrow here is. So states can have transitions depending on if they completed or failed. And then we have a series of custom tasks that we built for each different state. So in this one where we try to find the smart object, we have this try set character input state and find smart objects. And what this does is it just says, hey, the character wants to walk. They don't want to run anywhere. And we hook into the work that Caleb's done to kind of control the gait and speed of the character at that point. And if you're curious about the types of tasks that we have, if you click on this button here, we have a breakdown of all of our animation sample tasks on the right. So it says animation sample, and then here's our smarter objects ones and our state tree ones. And this is how you can add them to your own project if you want. State tree, going very fast because there's quite a bit to talk about, and it's very complex, so I apologize. But state tree does not come with a ton of tasks for you. You kind of have to build them up for your project. And ideally, what we've done here is this is stuff that we built that's pretty generic that you can use for yourself. So next, we kind of find us, we try to find a smart object and we have a few options for this in the way that this is set up. Basically, it just does a search based on box extents here. And there's a couple of different ways that you can kind of search. There's closest distance, farthest distance, and then random if you'd like. And you can play around with that in your project. And you'll see some various different behaviors that the characters will exhibit just based on changing this search type. If there is one that is a slot that is available, it'll come down here and actually claim that slot. And this is the thing that is really important about smart objects, where once a claim has been made, when another character tries to do that search, it actually won't return that that slot is available anymore. So once it starts using it, we call this use smart objects. And what this does in particular is it reaches into the smart object that it wants to use. In this case, we'll call it this bench. And it will actually look at the smart object definition that's defined on that bench and say, what am I supposed to do? So opening this up, this is the bench actor here. if you want to turn something into a smart object you add a smart object component and then you need to give it a definition and definition files are basically little data assets that define you know what slots are available to take over and then on top of that what is the behavior that you want to have so in our case for the bench here this is where we define launching that particular new state tree Once it jumps in here, it's now kind of, if I hit play here, and we watch these characters, as soon as they start walking to a bench, they're using that smart object at that point. And it is running this particular logic here. If you're curious and you kind of want to see what's happening, StateTree in 5.7 has a new debug feature. And we've tied it to the Rewind debugger. So I'm going to click this guy here, and I'm going to record when we launch. And you'll see him walk and sit down here. and I'm just going to stop. And if you haven't used the Rewind debugger, it's really awesome because you can see all of the animation and motions that are happening. But now the new smart object setup is in here and you can see all those different states and kind of what's going on for debugging those smart objects as well as on the frame it made the decision, you can see what exactly happened here. and you can see the AI smart objects. And then you can also see the actual tasks and states for going and sitting down to the bench here. So once it sits down, it's in the play loop at that point. You can see what's happening. So that's kind of state tree at a high level. The main thing that we wanted to show outside of showing like, hey, this is the brain, we're entering a bench, we're playing a loop, we're playing an exit, and then we're kind of going back into our patrol, is this task right here. So we wrote this new task called evaluate and play motion match montage. And its goal is to test as the NPC is walking towards the bench if it can motion match well into a smooth sitting animation. So there's a couple of things in here that are really important. The first one is we also now have an example of chooser proxy tables. This is something that I think is really good for setting up scalable projects. But the main thing is for us, for the smart object setup, is that you can make a new proxy for that vending machine that I talked about where you can have a different set of animation data that gets chosen, but using the same properties and expectations that the system wants. and then there's this cost threshold thing here and what this does is as we're walking towards this bench it's measuring the pose as well as the distance to the bench to turn to say like am I good enough to motion match am I good enough and it's gonna always return a cost the lower the cost the better and we set it to one and so what ends up happening is as the character kind of walks I I don't know why the camera keeps snapping, but as the character kind of walks towards that bench, disabled, that's why. You might have to eject in the rewind debugger. Oh, I'm not playing. It was this setting here. But as the character is walking here, they'll start to motion match. And then once they hit that point, they'll start playing that montage. For the chooser, here. We go back to our content browser, and we go inside the bench. This is the state tree. This is the definition. And we also have our animation setup for the chooser table. I think Caleb is going to talk a little bit more about another new feature that we added in 5.7. I'm learning that the MPC stuff is a crash course in all of our crazy new features. um uh so we have in this in the bench setup here we have all of these different uh entrances in total though it's only about 12 animations that make up the entrance um with uh the thing that tony was kind of talking about um where we have left and right mirrored animations we're not like taking one animation and mirroring it we have some custom ones for each one and our different approach angles. And then here we have this pose match column where this chooser is running through, testing the target angle in which the character is entering, and then pose matching and returning that score as a part of just doing the chooser evaluation. And if we look at the database for this, these are all the animations that we have. and you'll notice as I click through this, we've got this big circle here that debug appears and this is the new addition for smart objects that we added where there is a new channel where you can search against the distance away from your entrance point. And as it evaluates that, it will return a score and then kick off the animation. So if we go back to our bench here, once it hits the score, it'll kick off the animation. And then once it does, it will play until that entrance animation is complete and then start to hit our other loops and exit points inside of here. I just want to jump in, if I may, um as we i forgot to mention it uh at the beginning um but what dustin has said is essentially we've merged motion matching and choosers together so originally what we would do is we would have a chooser that would output an array of animations and then do another motion match function on that array of animations and that was fine but now what we've done is is we've taken that, embedded it into a special column in the chooser called the pose match column. And now the chooser owns internal databases rather than separate database assets. That column is essentially like a dynamic database that has been created in that chooser. And that is a really powerful way to work. There are gonna be some changes to how that works. I think in the future, it's very early on. And I'm trying to think what are the important things. So right now, there's just gonna be some differences for how the schema works with the database and all of that. But yeah, I just wanted to stop there for a second and just say that that is a really big thing that has been added. And we've also converted our traversal system to use this approach now as well. So now if you open up the traversal choosers, those animations will have a, that chooser will have a pose match column on the end of that chooser to do the motion match. Anyway, so that's really exciting. There's more to come in that space going forward. So yeah, it made scripting this much, much easier in the long run as well, where just running the evaluate function was really easy. yeah so kind of coming back to this I'm just going to open up this this task this is one of the tasks that we've written and it's all marked up with some comments of how it flows and functions here but if I zoom in specifically if we're on a server or not depending on kind of how the scoring goes uh this is the function here evaluate distance and motion match uh that gets run and the main thing here is that this task uh goes and talks to that component that i mentioned earlier where it will run that uh smart object uh proxy um again with choosers and scalability this is relatively new. It's been around, I think, since 5.5, I believe. But we hadn't kind of shown it off. And there's not a ton of documentation here. But the goal with a proxy chooser is that you kind of define what the input should be in their generic. And then what you can do is when it goes to evaluate, you can pass in a specific table to evaluate against. So in this case, we've kind of scripted this up so that the table that gets passed in is from the smart object itself, or specifically this state tree here that is kind of the brains of the whole operation. From there, the components that I mentioned, this AC smart object animation component, It has a lot of similar characteristics to the vault. And I think it's the vaulting component that Caleb has for the traversal component. The traversal, thank you. For the traversal component. But its main job is to run the animation data and handle networking. So one of the things about State Tree that's really important is if you're in a networked environment, the State Tree for NPCs only runs on the server. The client doesn't run it. And that is a problem for animation, especially for like putting the brains over there. And then we want to play animation. We have to tell the clients to play animation at that point. And so this component helps that. And the paradigm is pretty good. If you are a team that has really good networking expertise, there's some other versions of this that you could do. But from our perspective, this is a way to keep the systems really clean. Like the brain is over here, the motor is over here, and followable in terms of how it's designed. And I should point out that, sorry for interrupting, but if you're not in a networked game and you're just single player, all of the stuff in that component that doesn't add it could just be done in the state tree tasks. which would definitely simplify the setup for a single player game. That's originally how we had it done. And then we were like, well, wait a minute. I don't know. We have to demo networking and then all these extra steps. But yeah. So when we go to play the montage that we play, there's a couple specific things that we do for smart objects. The first one is Mover requires a different montage play. So there's a check here for if we're Mover. This is just the way that Mover handles... The reason this exists is because of the way that Mover handles callbacks separately from the CMC. But generally speaking, the rest of the logic is very, very similar where we handle looping as well as some other things here. but the main one is we add a warp target. So I'm just going to go back to our rewind debug and I'm going to turn on our alignment debug here. So as we approach the bench and we start playing this montage, that's what this is right here, signifies right here, you can see this blue line. this is a warp. And in some cases where if the character was approaching from the backside, it will, you know, we have one montage that's kind of relatively straight for this angle. It will align the character towards that endpoint. And we have a new warp for this that was introduced in 5.7 that we pulled over from the 5.7, or sorry, from the Witcher demo where now if we go to our animations so mannequin animations all of our interactions are in here. We go to, let's go to this back left entrance here. So in our motion warp, in our config, we have a new warp type called the pre-computed warp. And this is really important for the Smart Object Setup because it does something a bit different from allows you a bit more control than the skew warp. So very specifically, it allows you to control where in the warp window you are going to be warping for translation separately from warping with rotation. And there's a bunch of options in here, but the main ones here are our translation warping curve, where you can define the curve type, where it starts in the warp window, and kind of where it ends. So in this case here, we're warping from the beginning to like right about here in the animation. And then for the rotation warp, we're actually only doing our rotation warp from about here to the end of the animation. And one of the final pieces that makes this warp really, really good for the smart object setup is that there's this steering setup now inside of the warp. And what that does in particular is that if we scrub this Rewind debugger, we're kind of warping towards our target. But what it's going to do is it's going to kind of steer the character and the warp itself in a nice arc based on the settings that are inside of that between your start point and your endpoint based on that translation and rotation windows. So depending on your tuning, you can actually get characters that kind of like S curve towards your target as well. So it's really, really cool. Lots of little tunables in there. And you'll see some things happen if, let's see, if we can show it. Grab this guy. You can see some things happen where the warp will arc. I'm going to zoom in a tiny bit more. The blue line here arcs out and then it curves a little bit beyond. This is tuning. I don't think I have the absolute best tuning in the world, but for the sample projects here you can see like this is what it would have tried to do with the orange line and then if the orange line was adjusted it just does this and what the steering allows us to do is go from that start point arc nicely through between what it wanted to do here and get us to that at that point okay so i think last piece here is I wanted to talk a bit about the networking aspect of this, just to kind of touch on it, because I think it is important. If you are curious about how the networking side of this works, if we go to the bench and we go to this value way montage, after we test the distance and we say, hey, this is the animation that we want to play and everything, there is a call here called play montage multi. and very specifically this will work in single player as well but the main job of this is you pass in this animation payload of start time what montage you want to play the warp target where we gather that warp target from the smart object itself and that all gets passed through to that component where it does the actual replication right here so if you're jumping jumping into the project and you're trying to learn a bit more about how you can handle replication in a blueprint way, this is one paradigm that you can take. And the main thing is that this component lives on something that can replicate, like your player character or your NPC character, where oftentimes we're trying to replicate other things like position and whatnot. So if you want to learn more about StateTree, James Keeling, I'll put this up here. James Keeling did a tutorial about StateTrees in the first 60 minutes with it that you can follow. This is a really generic AI with a box kind of example. It doesn't use the animation part. But I think in general, because State Tree is really generic, you can use it in a lot of different scenarios. And follow this and it will kind of demystify a little bit of what's happening inside of the game animation sample projects. And we want to explore State Tree with other things in the future, with the future of animation tooling inside of the engine as well. so uh it's it's really good to jump in now and kind of start breaking this stuff down if you're a tech animator or a tech designer so i think that's it that's a lot to cover in a very short amount of time but um yeah it's good yeah thank you dustin um i guess i'll pass it over to jack to talk about the control rig and then we'll get to justin uh towards the end for mover so Let's do it. All right. OK, let's talk about foot placement. All right, I think you can see my screen. I just wanted to start with explaining what this thing is trying to do, what's the problem we're trying to solve. So let me turn on some debug. Let's wait to see things. You actually need to click this debug button and this Control Rig debug button, because all debug from Control Rig is gated through another C var. So here you can see there's some debug on the legs. So that shows there something happening here If I run over or walk over this terrain you see that there a bit of divergence between these two sets of legs So the light blue, the cyan ones, are the animated input. That's what's coming from the animation system into Control Rig. And then it runs through a load of stuff that I'll get into. And it gives us the green legs, which is the corrected legs. If I just turn the whole thing off, you're going to see that it's floating on the terrain, which you don't want if your game has any sort of slopes. But that's generally what we call slope warping, let's say. And it also corrects for cases like this where your legs might be just floating in thin air. You'll see if I turn this on, it's going to put this foot on the ground, And it's going to realize that, hey, we need to move the pelvis down in order to reach the ground. Otherwise, we're just going to have a hyperextended leg. So we call that like obvious relaxation. But yeah, you can see there, I toggle it on and off. It's also doing what we call foot pinning, which is a little bit harder to show. I might have to go in slow motion. As I walk around, you'll see these white circles on the ground. And if I go into the Blueprint, it's a good opportunity to show you where this is integrated in the new animation Blueprint. This is a specific one for Mover. You won't see this in the CMC one. You can put it in the CMC one. You can hook it up. Leave that as an exercise for you to find people. Should work. But here, you'll see there's a few huggles that are hooking into, like, you know, I don't want to do these effects if I'm jumping, necessarily, or sliding. So these are exposed as pins from the control rig. So I'm just going to turn off pinning just to show you what that means. And now if I switch back here and start moving around, oh, hang on, do I need to restart? Yes, there we go. OK, so you don't see white circles anymore. And it means if I go in slow motion, you're going to see that if I walk in a straight line, everything is good. If I start rotating, you'll see, and this happens in a lot of games, that you get a lot of foot slide. And that's normal because characters, we blend everything in character space relative to the root. So when we blend from one animation to another, or if we just rotate the character, like Mover wants to rotate the character to steer, we're going to get foot slide like that. And we don't want that. So there's a trick you can do, which is remember where the foot was in world space when it planted. And then you can kind of pin it to the floor. And that gives you an effect that, turn this back on. Hook that in. Save and compile. And hope that maybe you restart. There. Now let's go back in slow motion. You're now going to see that when I turn, you'll see a lot less sliding on those feet there. See, they're pretty much pinned in place. And actually, if I try and steer a lot, you'll see quite a bit of divergence between those green and blue skeletons, even though I'm walking on a flat. And that's because the pelvis is also being moved a little bit, just to be sure that he can reach the pins without stretching out his legs too much. There are limits to this. Like if I go to a completely different animation, then the pins can drift and cause a bit of slide, because ultimately that's better than having two legs right at an angle. And that's all configurable in the Control Rig settings. Yeah, that's foot pinning. That's the second thing this Control Rig does. The third thing, third and final main thing it does, is what I call root damping. So I can show you that real quickly. again by turning it off. So if I disconnect this pin, this effect is going to be off. And now, something you see in a lot of games when you go over bumpy terrain like this is you see a lot of shuddering. I hope it comes through on the stream. But here we're going up and down. And even if I smooth what his feet are standing on, because if you see here, I am still smoothing his feet, but his whole body is jumping up and down. And that's because if I put the collision on, if I can find the button, there we go. It's normal that the mover is going to collide with this ledge pop up, and it can drop down. That does cause a discontinuity in the animation. So what we can do is add an extra bit of smoothing on the root bone and do that in world space. And that really helps for these type of things. So I'll just put that back on over here. And I just tie it to the same. If I want a slope warp, I tend to just want to do this all the time. So I'll be on the same function. And now, see it's much smoother. And you'll actually see at the base of his character, you see a little line that's like a yellow and purple line. But that's showing this effect. That means when I sprint over this, you see it's totally different. It's much smoother. We've got the camera attached to the root here. So it means that we're getting that smoothing. It's important you don't attach to the actor if you do this because the actor is still going to jump up and down. But yeah, that just helps smooth out the whole thing. So it's a nice, buttery gameplay. And it's really important with that effect that you don't want that on when you're going up slopes. So you see here, you'll see that you won't see a divergence on that pin at the bottom when I'm going up this slope. So this spring is designed to only work in the direction of the ground normal So that means that here we not going to be dragged into the floor when I run up a slope It just going to take effect when I go over these little curbs So that generally what this is doing I'm going to go into the control rig. I'm not going to explain every single node, but I'll at least show you how you can build this type of thing or how you could, if you want to tweak it, be my guest. This is your thing to play with now. I also want to just first talk about why we're doing this. So like Caleb mentioned, we do have some nodes. If I open up CMC Blueprint, you'll see that we do have these nodes, and this is what we shipped in the past, foot placement and leg IK. So this is how we used to do this. These have always been experimental. So their flag does that. They ship in an experimental plugin. I think it's called Pose Warping. Correct me if I'm wrong. Is that right, Caleb? I think that's right. Yeah, anyway. You should know, but I don't. Yeah, I mean, I can find it. I think we're good. But it tends to be a bit of a black box. Like, you had some settings exposed, which you can play with. But it's pretty locked down. And unless you're an animation programmer, obviously you can get the source code and play with that. But it felt like, well, hey, if you have a horse and you want to do some quadruped IK, maybe this will work, maybe it won't. And if it doesn't work, you're going to have to speak to a programmer. So we were really interested to shift and start using more graph-based workflows so that the technical animators in the room can play with it too. And I think it'll lead to a lot of experimentation. I want to say I don't think this control rig is the perfect unicorn control rig that will fix all of your foot placement issues for every game. It's really just a starting point, and we'll continue to work on it. We'll continue to optimize it. It's really a nice dog-feeding experience for us to push the limits. And we really see this as the future as we move to the new animation framework that Adi will be keen to talk to you about. That's really where we want to go. We want it to be RigVM-based, and we want these things to be visual and malleable without recompiling. So that's why we're doing it. So I think that's that. I will move on to how this thing works. So let's shut down the CMC because that's not what we're talking about. Look at the anim blueprint one I showed you. This is where we plug in. So if I start from the root animation graph, zoom in, we've added this layer here, procedural layer. If we go inside that, we'll see that we take the input pose, we just cache it, and then we feed it into this control rig here. The control rig has a lot of variables. I won't talk about them all. Some of them I expose as pins to Animation Blueprint. Let's look at the control rig itself. It is located in Blueprints, Control Rig. Here it is. It's a bit of a beast. So like I said, I'm not going to go through the whole thing because that will send you all to sleep. I'll just show you. I'll just explain the big picture of how it works. And it's also a pretty cool showcase of what you can do with Control Rig at runtime, which I think is awesome. This was the first time I really built something with Control Rig, something this complicated. And it was a really fun experience for me, because I've written systems like this in code multiple times. And the turnaround time is much longer. Bugs go unnoticed. So it's really cool to have such a system that you can just play with in the viewport and see straight away what you're doing. So here we are. We've got Control Rig, and we've got all of these controls that I've added. You'll see that it's a pattern. I'm adding a null and then always a control under it. And this is something the Control Rig team let me know is a good and a best practice to do. Because you don't necessarily need to do this. You could just work with controls all the time. But the issue, if you start setting controls procedurally, you're going to find that you can't play with them in the viewport anymore, which is kind of annoying. because it's really nice to be able to say, take this and just say, hey, what would happen if I did this? Or if I start doing this, what's going to happen? And you want to keep that ability all the way through your workflow. And the way you can do that is if you always set your null but read from your control that's a child of it, then you'll always be able to play with the child as just an offset. And it keeps it all debuggable. don't have to have special booleans that override stuff or anything. So that's that. So this control rig is split at the top level into these processes. I think I'll just go through and explain generally what they do without getting too much in the weeds, so ignoring boring stuff like deep-up draw and teleport. The first thing we do is just store the input pose so that we know what the animation wants. And it's really important to know that we don't want to break the animation pose. So if the animation wants the foot off the floor, we want to respect that. And the idea is to just transform that to the ground space. So I can show you an example. This is a really nice way to debug this. You can go in Preview Settings, use specific animation. You can choose here, play a walk like this. I like to just turn off the root motion for this because I think it's easier. So let's do a run because I think his foot will be off the ground more. So if we take a relaxed run loop, thanks there, Tony. These are the best animations you ever saw. And yeah, let's say this foot's off the ground. So we don't want to do things that actually stick the foot to the ground, because obviously that would break the animation, right? So we always measure this transform away from the flat ground, and then we're going to sort of transpose it onto whatever we think our new ground is. So here, if I rotate this, you'll see that it's just going to ping him up a bit. And we can see, OK, this is what it would look like if he was walking along here. So to do that, we capture the target transforms. And we set, like I said, we have these things called animated toes. By the way, the toe is the thing that we really want to track here, not the foot. You tend to get much better results if you track the toe, which is at the end of the leg chain. We handle our global root damper, which I've commented here. It's kind of simple, this thing. It's mostly just using a spring. But this is a great time to talk about our new spring functions, which I'm very excited by. And big shout out to Dan Holden here, who's like the god of spring math in Unreal. I'm sure a lot of people have read his blog, The Orange Duck. So one of the first things I did when I joined here was to work with him to get these implemented in a Blueprint library. So if you go here, you'll see we have this critical damp spring, which can work on floats, vectors, and quotinions. And we actually also have this for those interested in Blueprint. And it's actually more types in Blueprint. So please use these functions. They're super useful. I think in Blueprint, we also have a few more. We have like so many now. Just a quick note. This is kind of like better interpolation. So a lot of users might be familiar with, you know, the float interp nodes, the vinterp nodes, all of that. But what those interpolation nodes don't give you is nice ease in in your interpolation. They just ease out. And so when we're tuning animation behaviors and interpolation, not having ease in can be super jarring when it comes to blends. And so these new spring nodes are super, super beneficial. And I think I added one of those to sort of a rework of the aim offset. but I can get into that later. I don't want to dive into that now. So that gives us nice ease in, ease out when we're tracking a world space rotation. So super exciting. They also... Sorry, the thing is worth noting, they also give you much more consistent results across varying frame rates or different time steps, basically. Yeah, that's it. Like, mathematically, if you just tick this node once and say what's going to happen five seconds in the future, if you have the same target and value going in, you're going to get the same answer going out as if you stepped that. So it's completely frame rate independent for a constant target, which is really nice. And it's pretty cheap as well. So this is just my go-to thing now. I'm using it. I think if I type springdamp here, I'll find a few of them, two of them at least. But yeah. So anyway, this is what we're doing here. We're going to dump this Z value. I just reset my controls. Should be able to see it. I have this pelvis. I have a little damp input. I see. I'm not sure if this is exposed here, actually, because I need to do it in world space. I'm not sure that I made a control for it. No, sorry. These are all zedamper is actually controlled as a variable here. And like I said, it's because deliberately this is all in world space. And that's how we make sure when we suddenly pop up, we're not going to. spring up. So actually, I can't make a cool control for it. Whilst the pelvis, when it sucks down, that's all in local space. So that one, I can have a nice little control that I can play with here. So yeah, that's just something to watch out for when you start doing this work, you think what space you want to work in. Right, so that's that. That's where all of the global anti-pop stuff happens. Then this is important. We need to find out where the floor is. So we asked to do some sink queries. Again, I'm not going to go into all of it. It's too much. But essentially, we do some sphere traces to the floor, find the floor, and then we smooth it. So you can see, I think I put a control for the actual collision that I got. Yeah, these will basically be placed exactly where the raycast hits, and it figures out the rotation from the normal. And then we have these smooth ones, which just damped towards, again, using dampers. And you can configure all of these stiffnesses, by the way. If you're in class defaults, I've exposed a load of smoothing values and such things, angle limits. They're all there. If you want to make that dynamic, they're the same values that you see in the animation blueprint, this is the same thing. Every single value in the class defaults here that's basically all the public variables of the control rig, you have the option to expose it as a pin or bind it to a curve if you want to make it dynamic. For our implementation, I'm really only exposing the switches, the switch on and off the stuff. But if you wanted to have different smoothing in different walking modes or something you could do that there Yep And then let see Once we've got that now, I exposed a little Boolean, like do raycast. And I think this is something I want to expand on to optimize this later. Because if you have 100 characters, you probably don't want to raycast every frame for every character. In Gasp, I think it's fine for the main character. Your hero character probably should do that. But certainly, tying this to an LOD would be a good idea. Tying it to distance from camera, whatever you want to do. I think you could just do raycast every few frames and stagger it out. It will cope with that and just smooth towards the latest update if you need to. And it's worth noting, if you're walking on a flat plane, it's OK to just raycast every 20 frames, and it's still going to walk on the plane. you don't need to worry that your foot's going to be stuck behind, because it's always kind of projecting onto this plane that it's found. All right. I hope you're still following. I'm not sending you to sleep here. We then do some smoothing. I'm going to ignore that, because you can just read about it. And then we get into the interesting part, which is foot pinning. And yeah, so footfending is an interesting one. We control it with curves. So you'll see that I'm querying this getCurveValue, getting these contacts. So I want to show you this because this will be important if you start using your own animations with this system. Let me just open up this animation. You'll see here that we've got these contact curves. Now these have replaced, I think we used to have foot velocity curves. Is that right, Caleb? That's right, yeah. Yeah, so we've ported over both old foot placement nodes and this control rig that used the same thing now, it's these contact curves, which is basically just going to be zero when the foot's off the ground and one when it's on the ground. We just had an internal script that ran, analyzed all the animations to place these. We do want to ship that one day. It's not ready for shipping yet. Something that actually, again, Dan Holden's been working on how to really efficiently analyze, process, animations, and batch so that we can just apply this to all 400 animations. And it just takes a few seconds. I don't know, Caleb, did you want to speak to that? No, I think you covered it. I mean, basically, there are some new internal tools that aren't in the project now, but hopefully someday will be, that Dan Holden was working on to do a lot of work to animations in bulk, basically. And so those contact curves were generated through that process. It's probably possible to make an anim modifier that does similar, but yeah, we just haven't yet. And quick note on the contact curves, one of the reasons that we sort of transitioned to use contact curves rather than foot velocity curves is that depending on the animations, the feet, the velocities can be pretty crazy and inconsistent across a wide range of gates, walk, sprint, et cetera. And so it's difficult to tune foot planting behaviors when you've got a curve that could be super high or super low, foot velocity that could be a hundred centimeters a second or a thousand depending on the animation. So the contact curve gives us a lot more consistent results, and it's also easier to edit as well. So if you have an animation where it's like, well, the foot seems to be sticking a little bit here with the foot placement node, you can just edit that contact curve and kind of change when and where that contact is going to happen far more easily than foot velocity curves. Yeah, I mean, yeah, just from animation slide as well. sometimes you're dragging your toes sometimes you're pivoting off something and so the the velocity can sometimes as caleb was saying very wildly versus like a run 180 pivot versus a sprint 180 pivot the feet can be doing crazy things and so i should note um sorry uh the old anim node version of foot placement which is in the cmc character still needs a foot velocity curve and so we were kind of like scratching our heads a little bit like oh well do we need two different sets of curves in every single animation. That's going to be kind of a nightmare. But we found out that we could remap a foot velocity curve, or I'm sorry, we could remap a contact curve through a new special node in the graph called curve expressions or something like that. I should open that up to see. But it was a new plugin that we added to the project, an experimental one. It's almost like the modify curve node. That's essentially what it's doing. But it's taking a contact curve, flipping it and scaling it up to give us a foot velocity curve or like a kind of a normalized foot velocity, which we can then feed into the anim node version of foot placement. So yeah, hacks all over the place sort of, but like it works and it actually works well. So that's what we did. Yeah, and actually just saw Jose has reminded me to talk, since I was talking about how we find the floor, I should talk about how we stopped clipping into walls. Let me just load the default level, because I think it's got better walls than my test level. Something we found actually just a couple of weeks ago was that if we ran up to these boxes, some of the animation poses are a little bit outside the capsule. So that means that you can, especially if you start running if you start running against this, it's possible that you might raycast and hit this geometry. And it would mean that we would start trying to kind of foot IK onto the surface that we don't want. And yes, we could just filter the surface by normal, but it would still be a problem for rocks and stuff So what we actually started doing was throwing rays We throw two rays So we go one forward to try and find the closest hit in front of the player. So let's say we try and say, where does the foot want to be? We get that from the animation. Then we're going to throw a, I say ray, It's really a 5cm sphere cast forward above that position in xy. And if we hit something, then we kind of stop there, and we're going to go down from that point. And that means that we're not going to hit this wall, for example. If it's free, then we just go straight down to where the animation wants. So that gets rid of these kind of problems. And that's what you see. Go back to the giant control rig, the ground collision stuff. You have this function, doSceneQuery. And you'll see here, this is doing a forward raycast. I even had a little bit of debug somewhere that I could turn on. See if you are lucky enough. Yes, down here. I think, well, I am showing it, so I'm surprised we don't see it. Let me just check. It's on. Ah, yeah, there's a separate little toggle for that, because it can be a bit noisy. So if I tick this box, compile, and then go back, should start to see, yeah, you see these red lines? That's showing all of the queries we're doing. So you can see that in slow motion and I run towards this wall, you'll see that I might start hitting the wall. And it makes sure that it's never going to cast forward into this collision. This is a little detail if you're wondering why I'm doing four shape casts every frame. Now you know. So this can happen. It's not happening too much now because we have stride scaling, which are pulling the feet in. But if you had a super wide stance with your feet and you had a pretty narrow capsule, and you're up against a wall, that foot is going to go through that geometry. Because the raycast is just kind of raised the foot up, even though it's in. Yeah, I think you can see it happening here in the crouch idle. Yeah. See that it went and it hit the wall here. So it's gone back and cast down from here to be sure that it's clear of the wall before it goes down. So yeah, I mean, again, it's something you could turn off if you are at distance and you don't care about that and you want to save some physics checks. But I think it's good for the hero character to not be doing that. And it means Tony's still free to make cool, idle poses. You don't have to bug him about keeping it inside the capsule. Which we don't have to do, because he's always really good about that. Oh, no, he's great. I've done that a lot. Well, it's just one thing about we cast to the toe position, and the toe is at the end of the foot, so it can be a bit dicey. Cool. So yeah, that's that. You know how pins work. I'm not going to go into the math of it because it's just too much and it will take too long, but I'm happy to answer questions at the end. Finally, we place, we figure out where we want our legs. We have huge functions that do that. Let me go into it because I'm worried about taking too long. And we update the pelvis. And this is pretty important stuff, actually, because this is what is going to make us relax. And there is some tweaking. There's some magic numbers in here. Maybe I can even show you if I go into an idle loop. Let's see. Let's take a relaxed idle. And then if we make him play an idle on a slope like this, and we actually move the slope down. So if we go down a bit like this, see him. And you'll see he still looks pretty chill, pretty relaxed. And that's because it's enforcing that he always has to be as relaxed as the animation wants him to be. And I think it's maxed against this hyper extension limit factor, which is really important. If I set this to 1, you can see that his back leg starts to straighten up a bit. And that can get a bit dangerous when you start to play with things. And you'll see that it starts to feel a lot more snappy. I think if I turn off this debug, turn off the debug so you can see it better. Yeah. Let me show you. But basically, you see what we'd say poppy knees or snappy legs. And it's just part of the way mathematically, when you get very, very close to the max length of the leg, there's a lot of angular difference in the knee joint or just tiny amounts of just a few millimeters of movement. So it basically makes the leg seem like it's moving really fast. And also, to humans, we can look at it and say, oh, it looks a bit painful. So we can limit that here and enforce a certain amount of relaxation. So I thought that I might think I'd unput 9-8. I think that's a good number. But you can play with that. So if you think your animation is legs not straight and you want it to be, you can play with it there. Yep, so that's that little aside. Finally, let's see. We then move the pelvis. That is smooth in local space. I'm not going to get too into it. But there another one of these spring nodes Yeah it true actually Before I was talking about critical spring damp There critical spring damp and there just damp And these are both new nodes. Basically, critical spring damp will give you a continuous velocity. So that gives you the impression of momentum. Whilst damp is just going to go from your current to your target. It's kind of like through in a critically damped way. So it's through some sort of viscous fluid you could imagine. But it won't have memory about what direction it was going in the last frame. It's a bit cheaper. You don't have to store a variable to remember the speed. So I tend to use Damp because it's cheaper and easier. And when I think, oh, I want a bit of momentum and weight behind it, I'll use this one. So you can play with that. So that's what I'm doing for the pelvis. And then we do the actual IK solve, which is really just a basic IK on both legs, like two-bone IK. It's not full-body IK. We could, at this point, go through a full-body IK solver. It will be slower, but might get better results. So I'd be curious for someone to try it. I'd like to try it one day. But I found I like to have just control over what the leg is doing exactly. So I think it's good to just keep it simple and just solve the leg system in isolation. That could be changed here, because at this point, up to this node, we're just placing effectors, and then this is where we're going to modify things. I want to just draw your attention to this little web of noodles, because this figures out where our pole vector should be, which is this thing shooting out of his knee. You iterate on this a lot, and it felt like there was always a corner case where the knee would solve in some weird angle until we finally ended on this solution, which basically uses the side vector of the knee crossed with the target position from the upper leg. And that kind of forces you to give you this sort of 90 degree solving angle as dictated by the animated knee. And that gives you a pretty stable pole vector. And it's not obvious. I mean, we're working on making this node a bit more friendly. But I found if you try and work with a direction, even if you know what direction you want, things can get a bit funky. Because internally, this gets converted to a location anyway. So I'd recommend just feed in the location you want and figure it out. And there is actually a function we're shipping to calculate pole vector, this one. It comes with Control Rig from the standard function library. But for this use case, I was getting worse results with this than if I used this method. And I think this is fairly simple, so I would look into it if you're having issues with your pole vectors. Yep. And then finally, the last bit of the magic, again, I think it was Dan Holden that was like, hey, I did this on a side project. It's pretty cool. Is we do a little bit of collision detection with the floor just to help fix up any last clipping we have. Because when we move the pelvis and everything, it's all smooth. And it's possible that we couldn't really get exactly where we wanted because the pelvis isn't in its target position yet or whatever, and that can lead to some last minute clipping. And also just due to the rotation of the plane, like you can sometimes have some clipping, especially on like run animations. So if I play like a run loop, relaxed. Montoni, where you're going? Oh, no. Oh, no. What? Did I choose the wrong one? No, you're good. You don't scare me like that. My job to keep you on your toes. I know I am. Is that a pun? Like the characters on his toes. Yeah, exactly. Start with a pun, guys. Make sure to roll through the ball of the foot to the toe, to the heel strike. I want to make sure there's every single bit of those in their mouth. That's it. That's it. So I turn off these controls. So you'll see there's actually a little bit of collision detection going on with the toe. And it's pretty subtle, but you can see as I rotate the plane. I know you can't see the plane right now because I turned off the debug. But his toe will actually, the end of the toe does a little bit of a final collision just to make it look really planted instead of shoving itself into the plane. And that is handled in this update for post-solve. I think it does a couple bits of collision detection. It does the foot to toe with the plane. It will correct that. And then it does the toe to the toe end, which it also corrects. And that just will help you feel a bit more grounded. That's it. That's generally what this control rig does. Did I forget anything, guys? Actually, there was like three different times I thought it was going to end. And then there was like, and then there was no question. It keeps going, eh? And more, and more, and more. That's like every single bug report you file, it's another one of these branches. Yeah, that's right. It was like 40 minutes of control rig. Oh, my God. Is that 40 minutes? I'm so sorry. That was okay. Yeah, Nick, I think it's a good time to get to the mover section of this. So I'm going to hand it off to Justin. All right. Thanks. Yeah, so switch gears here for just a minute. But basically, I want to talk a little bit about some of the high level things that Mover is providing here and talk about how they've been applied in Gasp. And then I'll also walk you through just a little bit of the dead simplest setup. Like if you wanted to start using Mover, how to set up a pawn from nothing and have it move and move and dance and all that. So first off, why do we even need this Mover system? And how did we apply it? One of the big pillars of it, big motivations, is its modularity. So if you're familiar with CMC, the focus is on movement modes. So Mover has movement modes as well, but they are modular objects. You can swap them in and out. You can add any that you can dream up. You can use some of the ones we have built in or reject them. You don't have to burden your character with them. You basically don't have to pay for the things you don't use. That's sort of one of the principles. So how that played out in Gasp, we have a base walking mode that's included with Mover. It is roughly equivalent to what CMC does as far as, you know, it assumes you have a capsule that kind of wants to stay upright. It sticks to the floor no matter how the floor changes. And if you hit obstacles, it might try to pop up and over them. Pretty simple. But what Caleb and the animation team wanted to do was put together more of a change in how acceleration and turning went, as everything is very linearly interpolated with the classic stuff. So they put together a couple of new movement modes. I believe they're called simple walking mode and smooth walking mode. And they use different curves like Jack was talking about, the different interpolation methods. So those are employed there. And that was something they could do just building on top of our existing walking mode while still using the behavior that was there. So those in particular, so those were done in C++. But we don't want to limit people to that. So blueprint extensibility is a big thing that we care about. So you could also just as well make your own blueprinted movement modes. I believe the sliding one was something Caleb had done where he took one of the smooth ground movement modes and extended it to be more like you're sliding on the ground. and just changes how friction is dealt with and all that. But so there's no example in GASP, I think, of a just absolutely from scratch movement mode in Blueprints, but it is possible. And I believe with 5.7, as certainly in the 5.7 release, there is a mover examples plugin that's included with the engine, and it does have at least one example. I think it's a flying mode that is 100% done in Blueprints. So that is an avenue open to you, your tech designers, anybody who just doesn't want to get their hands dirty in native code or doesn't want to deal with the compile times, I can respect that. So modularity is not just limited to these movement modes, though. So another thing at play here, there's the data that Mover is sharing around. So one big difference between CMC and Mover, when CMC wants to make a move, it's basically telling the server, hey, I tried to move with this acceleration. And here's kind of where I ended up. Here you go, server. See what you do with that. Server does the same thing, compares its results. and the server is like, yeah, that was good. I got the same results or now we're different. So here's what actually happened. So in CMC, all we're sending is like acceleration and some little data bits and our result. Mover, we are only sharing our inputs or what we call inputs. So this could be data about how our controller move input is. It could be from AI. They might be requesting a specific velocity. It could be data bits about like, oh, am I trying to jump? Am I trying to slide? Am I trying to do whatever ability your game has? That all gets rolled up into this input struct. And then that's what actually gets replicated, sent back to the server. And it can be shared all the way to the other sim proxies if you so desire. So the modularity of this input, we can add at the game level, whatever inputs you come up with, you can add to them, and you can add to them dynamically. If you have a new ability that you got from some power-up or something, you can start adding some new inputs to your movement that pertain to that ability. Similarly, what we consider your replicated movement state, it's the same thing. It's just a collection of data structs, and you're allowed to put whatever you want in there. And something that's recent that we did for this project, we started previously, you had to define these structures in C++, But we found that pretty limiting, especially for GASP, which is supposed to be a Blueprint-only project. So we did stand-up support for user-defined structs, which is like a way in Blueprints to define your own structures. And then we have some library functions for adding them. Yeah, so it's very common for CMC users to have to actually modify CMC, the code, to support additional inputs. But now you can do that potentially without any code changes whatsoever. Input production, I've hinted at, that's a little different. I'll point that out when we get to the example. But one thing to point out in GASP, we did actually... opt to share the inputs that a player is generating Not only are they sent to the server but they also passed on to the sim proxies And so there some data inside the input that gets fed to the animation system I don know Caleb if you have an example of what that is Uh-oh. Yep, he... Oh. It had to happen, okay? we had to have a crash and we had to have a microphone well as long as it's all we've gotten that out of the way yes well anyway yeah bottom line uh it was it was yes something that informed how the characters rotated whether they wanted a strafe or not uh that uh allowed the animation blueprints on the sim proxies to be you know uh to to do this the song and dance a little a little bit better than if they only had the movement state itself. So yeah, so that's good. Some maybe less obvious stuff about Mover. I had mentioned modularity, something like nav support. Previously, with CMC, if you have a CMC character, you have inherited all of the functionality, memory footprint, everything of using like nav walking, nav movement mode, all that stuff. So we have it optional. So if you did want to set up an NPC that does these things, now you have the optionally you add another component to the mix and use a separate movement mode. Something that was valuable for animation purposes, Mover makes it pretty easy to generate, like predict your future trajectory. So based on my current inputs where I am, how am I? Give me a sample. Give me 30 samples in the next second of where my character is probably going to try to move. So the good thing about that is that is running the exact same code that the movement simulation will use as is predicted. And that's sort of like a key for motion matching. I think with CMC, they had some predictors that were like estimations. They weren't quite as good. They were pretty good, but they certainly wouldn't apply to anybody who created custom movement modes. So this is actually using the same movement generation code that would occur during the simulation. And there is a separation of like, you know, how are we trying to move from actually executing it? there is a bright line between those things, and that's something that this allows. Some other things that you might have heard of what we did at Unreal Fest with the Witcher demo, where we had a lot of mover using NPC characters. All the movement simulation was done off of the game thread and in parallel. That's something that the doors are open to that and we'll be continuing to work on. And also opening the door to physics-based movement. If you are a UEFN user and have played around their physics islands, that is a character that is using Mover plus Chaos' networked physics system, which is getting a lot more use coming together. And it's pretty fantastic. There is Tom Watterson and Marcus Boberg did a talk at Unreal Fest Stockholm this year. I don't think it's been posted yet, but it should soon. They'll have a talk all about the experiences with that. So given that we're maybe a little short on time, let me just jump into a little demo I wanted to do. So here we're going to jump it over to this screen. Basically, we're going to set up the dead simplest pawn possible. So this level is one of our third, just our third person template level from stock Unreal. This is Unreal 5.7.1. So I don't have any source code changes or anything. This is just vanilla. Everything in here is vanilla. And I have this pawn I've created, which is very, very simple. It's just a very simple capsule with some shapes on it. It doesn't really do anything, but it has a camera attached. So as you can see right now, if we run, it will spawn, but it has no motivation to move. It doesn't have any movement component on it or anything like that. So it just kind of hangs in the air. So let's do some setup here. So open up the pawn itself. So first things first, we need to make sure our capsule collision is something reasonable. I can see here that's not quite what we want. This is going to be a pawn, so we're going to change our collision presets and save that. then we also want to add a mover component. And just for simplicity's sake, I am going to add this one, which is called a character mover component. It is just a raw mover component with just a little bit of extra API and some movement modes to get started. You don't have to use that one there if If you were making a character or a, sorry, a moving object, it's like just a simple platform or something, you probably would just use the regular Mover component. But this one gives us a couple things. It's primarily just these modes that I care about. So walking, falling, and flying. And from the get-go, you'll see he should be starting in falling mode. So let go back and make sure that that works Yep So he moved but I don have any way of controlling the character So let focus on that for just a second And this is actually where I think a lot of people new to Mover get hung up. It's this how we deal with producing input, wrapping it up into this package and passing it along to the movement simulation to use. So first things first, let's go over here. Before we do anything, I'm cheating a little bit. I've got this stuff kind of prepared ahead of time, but basically we are going to grab our controller and add our input mapping context. So this is for the enhanced input system and there is a preexisting mapping context. I can show you real quick. Very simple. It just has some things for moving, looking, jumping, and flying. We're going to be focused on just the moving today. So, whoa, we got you. Sorry, I'm back. All right. Welcome back. Restart my machine. Sorry about that, everyone. All right. The good old classic, turn it on and off again. All right. All right. So we're going to add our movement event. So when it gets triggered, we're basically going to hook it up to this. And really, all it's doing is saying, you know, get my, this is effectively controller input, whether it's from a gamepad or your keyboard, converting it into camera space or control rotation space, as it were, and then setting it into this locally saved variable. So this is the thing. I'm not telling mover to do anything yet. I'm just holding on to this input because input production comes in a discrete phase a little bit later, later during the frame. Yeah, and when this is done, we'll set that back to zero because there is no more moving input. So now comes the tricky part. So mover has what is called an input producer. So this could be something it could be on your pawn it could be on a component it it doesn't really care where you put it as long as it is somewhere somewhere on your actor it will find it and it will call it there can be there can even be multiples but we don't need to get into that today so basically something has to implement this this mover input producer interface and it is a very simple interface, just implements one function called produce input. And your job as implementer of this is you have to create the mover input command context structure. Luckily, I have a chunk to just kind of copy in here and make it a little simpler. and what it involves you're basically just making this collection of data like I mentioned before the modular collection of data structures here we only really care about one particular one but I'm actually going to work backwards I feel like this is easier to easier to understand, what we're making is this command context. So we've made one of these. We can connect that to the return node. Now what goes into the command context is a data collection. And if you are over on the other side dealing with movement state, it's the same thing as a state collection. And in our case, it's very simple. We just have one thing we want to stick into it, and that is some character default inputs. Now this structure is something that comes with mover and it is something that all of those movement modes that are built in, that's what they like. That's what they read and that's what they interpret as input into their movement simulation and it determines how you move. So all we're gonna hook up today is the move input. So that's, I'm trying to move in this direction with this kind of, I don't know, magnitude or strength. So everything else in here we will ignore, but if you are using a, if you're putting together a full game, you might fill out more of these. But that's pretty much it, is we just have this one thing that we saved from our input event. We're stuffing it into this data structure of character inputs. we're taking that we're adding that to our data collection and all of this is going into this structure that we are returning so it's a little verbose it is a it is something I think we need to we can improve this we can get provide some functions we can probably come up with something to make this a little easier a little clearer but until that time this totally works. Okay so now we have we should be able to go back to the game spawn it and now yep so I'm pressing the using the keyboard to drive around so the character is kind of switching back and forth between walking mode and falling mode. And I had mentioned this character was using the default walking mode, but maybe I'm a connoisseur of interpolation and I want to make use of some of the stuff that Jack and Daniel and Caleb had been iterating on so I can swap that out for the smooth walking mode So I'm doing this in the archetype that you could do this at runtime as well if you wanted to. And now you can see the character accelerates a little smoother and accelerates and turns a bit smoother. there's basically different behavior. Yeah, so that's pretty cool. One other thing I did wanna mention, this is something that is kind of unique to Mover as well. So we have all these different modes, but I wanna draw your attention to the shared settings. So this is something in particular, like some of the modes that we have built into as sort of like the defaults, they're all based off of how CMC, how they worked. And so, although the modes themselves are modular objects, we didn't want to have to have every single mode that you reference the same bit of data to have to duplicate it. So we have this concept of shared settings where this is also another object that your modes or anything else can refer to. So for instance, this kind of determines how sloped your ground can be before you can consider whether you can walk on it or not. So both walking mode as well as falling mode, they all care about this because falling mode needs to know whether I can land on a surface or not. So they both refer to this thing. There is no reason if you were to construct your own movement modes, your own movement set for your characters, you don't have to use this. It's perfectly valid to, you know, you could use a reference, a data table, data assets. Each of your modes could have their own settings. In fact, if you expand some of the modes themselves, they have their own settings that are unique to the modes. um so yeah just something to be aware of uh and uh somewhere where you're as a developer you're you're flexible uh on how you want to handle it so um yeah so uh sweet i don't know if caleb did you want to talk at all about the i sure difference between those modes yeah hopefully my mic stays working so that we can get through this. So far, so good. So far. And I think my, I'm sharing my screen again. Hopefully that can, does it work? Please work. I think it works. Yes. Okay. Yeah, sorry about that. I cut out for a little bit. And so I missed some of what Justin was saying. The one point that I did want to add where Justin had asked, you know, why we want to replicate those inputs to control the animation system. So we're doing a lot of work on the pawn, or sort of the mover pawn that we've included to do things like change our gate, change our movement direction, all of those things. And those are also bits of data that we want to use to control the animation system. And since we're already doing those sort of calculations of what do we want to be doing? Like, are we running? Are we walking? you know why should we want to do those twice you know on the animation side so we thought it'd be it'd be really neat if we could just replicate that data to drive the animation system and so when we're setting up a character and sort of adding new capabilities to mover like do I want to be walking super slowly or you know whatever or am I like am I in stealth mode right which might change the moving behavior we can use that same bit of information to change the animations as well. And so it's kind of like automatic replication, and you can drive the animation system that way. So it's really, really, really neat. I wanted to do a little bit of a live demo to showcase how you can extend a movement mode in Blueprint, which is really, really exciting. So I'm going to do that now. So like Justin, I've also set up a very simple character, very simple pawn that uses a mover component. And to demo some things, I've got a debug graph there that shows the speed of the character. And so the first thing, well, I'll give you a little bit of a rundown of the setup. That's a very basic camera control. And then, like Justin's pawn, I've got a produce input function. And what this is doing, like he just showed, is it is setting the directional input, input and then I'm also setting the orientation intent here to also be the move input. And this is the character default input struct that Justin showed off and they were adding that to the collection and passing that off to mover. So the first thing I'm going to do here is we've got modularity here and we've added two, well right here, two new types of walking movement modes to the project. One is a simple spring, which uses a critically damped spring to move the character around. And if I demo that, you can see that I've got these really nice, smooth changes in velocity there. And that's really, really, really cool. What we've also added, or I should say, as we were working with a critically damped spring, we started to run into situations where we wanted to tune values, but it wasn't really clear how the values were affecting movement. You know, we've got stuff like velocity smoothing time and phasing smoothing time, but it's not very descriptive of how the character might be moving around. So what we ended up with was this sort of hybrid mode, which we're calling smooth walking mode. And I saw a comment that says that it has a memory leaf, which is pretty bad. So we're going to investigate that. And if it does, we're going to get that fixed. So but what the smooth walking mode is is kind of like a combination of the CMC mode, which used parameters like acceleration and deceleration, which are quite designer friendly, and then also a spring on top, which is smoothing out those changes in velocity. And so I can demo that. I'm just going to set some quick values here. I'm going to turn off smoothing. All righty, it should be good there. Okay, so I've got a character that can accelerate at 300 centimeters a second and then decelerate at 300 centimeters a second. And you can see it's linear, so we've got these harsh changes in velocity. But with the smooth walking mode, we have this additional smoothing that we can apply, which is like a spring. And so now, those changes in velocity are smooth. But we can still independently tune how fast we can accelerate the character and how fast we can decelerate the character. Like this. So now we're decelerating much quicker than we're accelerating. There's some other stuff in the advanced settings, some fancy things that are going on. One of those is this directional acceleration factor. And so as we were building this movement mode, there was kind of an interesting artifact that would happen when we would change our movement direction. So if I'm pressing W on the keyboard and I suddenly change directions to go at like a 45 degree angle, you can notice there's this dip in velocity there. And I wasn't a huge fan of that because it meant that every time you're changing your velocity, you're sort of decreasing your speed, which is physically accurate, but not something that you might want, especially in a game like a shooter or something like that, where you're going around a corner and then you're getting this sort of slowdown effect. And so we have this slider here, which kind of changes the math about how the acceleration is applied to be a little bit more similar to CMC. And so when we're doing small turns, like a 45-degree turn, we're maintaining that velocity a little bit more. And that's pretty cool. There's additional settings here. This affects how the spring works for acceleration and deceleration. So you can get some different profiles. And so it's much more responsive in the beginning, stuff like that. And this is all great. But what if, as a designer, I want to come in here and I want to augment this? Let's say I've got a sprint mode and I want to change the speed of the character, maybe the acceleration of the character, if I'm sprinting or not. We can do that by extending this movement mode in Blueprint. And I'm going to hopefully try to give a successful live demo, but we know how live demos go. So first thing I'm going to do is I am going to make a new blueprint. And this is going to be a type in smooth walking mode. It's going to be a child of smooth walking mode. Now, while I do this, there's another thing called simple walking mode. And Jack, do you want to explain kind of what that is and why we did that? Yeah, I mean, basically, if you extend from a movement mode, that's the base class of the movers movement modes, then you can Blueprint that. But there's a couple of functions you need to implement, because that was going to handle both generating your walk move, generating your move, sorry, which is where you want to go, and also doing the simulation test of, like, can you move there, which did you hit collision stuff? And there are examples in the mover examples that just shows how that works. So if you go there, it's like hardcore mode, and you can do whatever you want, which is great. But if your goal is to basically do a walk mode that is maybe just a little bit different, then maybe you don't care about overriding all of those details. And since the API for that stuff is really flexible, it also deals with these generic collections. And we thought, hey, for a simple case of you just want to move based on, say, a desired velocity, we could maybe wrap that up and make that just a little bit friendlier for Blueprinters to fit their toes in it. People like you, Kalen, who don't want to deal with breaking struct arrays and stuff. That's right. I'm not good at math or vector math. Oh, I'm not saying that. You're great. I'm not. But, you know, it's good to reduce your needles. So, yeah, that's why we made the simple walking mode, which I guess you're going to... Sorry, it's so blurry here. I can't even read. Yeah, so I'll... And I should add that, you know, right now we have simple walking mode. We plan to do similar to, like, the flying mode and the falling mode and essentially make it easier for the Blueprint users to augment the behavior. So I've created a new Blueprint Movement Mode called Demo Movement Mode. It's a child of the Smooth Walking Mode. And the Smooth Walking Mode has a special function that we can override called Generate Simple Walk Move. First thing I'm going to do is I'm going to convert that to a function because it should be a function, not an event. And so here we get, this is essentially like the function that generates the move that is then going to be simulated by mover. And there's a ton of flexibility in here. But one of the things that I just want to do first is I'm going to add a call to the parent function and plug in all of this stuff. And what this is going to do is just allow me to make some edits to some properties, but then still call sort of the parent behavior. And I'm just going to put a sequence node together here to do this. And if everything worked I going to go to my Mover Pawn and I going to switch it to the demo walking mode The settings are reset but that fine I just going to confirm that it works There we go We have a character walking around with this blueprint movement mode. All right. So the smooth walking mode has a number of different parameters that we've been tuning here, acceleration, deceleration, turning strength, et cetera, one of those being the max speed override, which is overriding the shared settings value, we can actually, in this generate move function, access and change those variables. So if I type in acceleration, I can set that. And if I set it here in Blueprint to change acceleration to 10, now all of a sudden that's going to override what I've set in the details panel of that component. And you can see them accelerating very, very slowly. So what I want to do then as a user, if I want to make something like a sprint mode, I want to change these values based on states or inputs that I'm feeding in to the mover pawn. And Justin alluded to this earlier, but we can actually pass in user defined structs into mover so that we can have full freedom and flexibility to do kind of whatever we want, which is really cool. So the first thing I'm going to do is I'm going to create a blueprint struct. I should know exactly where that is, but I don't. There we go. And I'm going to call this mover demo inputs. All right. And then I'm going to add a variable here, and I'm just going to call this sprint. Okay, and save that. So then in my mover pawn, what I'm going to do is I already have this variable saved. It's just the mover default inputs, and that's the character default inputs that mover provides. I'm going to add a new variable here, and I'm going to find the struct that I just made. Demo input, or yeah, custom inputs here. Mover demo inputs. All right. And then in the event graph, just to get sprint working, I am going to make a really basic input action called sprint. Sweet. So now I've got this value called sprint, which is just on the shift key. But I need to pass this into mover so that the generate move function can get this. All righty, so in my produce input function, I've already got some stuff here for the default inputs like I've showed. Now what I can do, if I get this struct and I want to set members in this struct, so set member in the mover demo inputs, expose this. Okay. I'm just going to feed in my sprint value. Now I'm not done because I have to add this struct to the data collection, which is then fed to mover. So I'm going to copy this. I'm going to do another one of these. And this input collection is just a local variable that I've saved in this function so that I could pass multiple things into it. And I've got a wildcard here, which means I can take the struct that I just modified, mover demo inputs, add that to the collection, and now I'm sending that data into the input collection that Mover is going to use. So if I go here into my movement mode, add another sequence, and what I'm going to do is I'm going to get the start state. There's kind of like a bunch of different structs here. it can be a little bit confusing at first because you have to break them and they become different things. But the start state gives you the input command here, which are the inputs that are coming into Mover. And if I break those, I get the input collection. And from that collection, I can type in a function called get data from collection, which is going to extract a specific struct from that data collection. Now it is a wildcard here. And so if I drag off of this, it's like, I don't know what, it doesn't know what to get here. So it's a little bit confusing because we need to know what we want to retrieve, sort of in advance. So I'm going to create a local variable here called, well, I have to change its type to the custom inputs that I've made. So move our demo inputs. inputs. And I'm just going to cache essentially the inputs like this. So now when the generate move function updates, it's going to get the demo inputs or essentially the custom inputs that I fed into Moomer. And from that, we break this, we can get our sprint state here. And so what I want to do, like I showed before, there's a max speed override here, is based on my sprint state value, I can set this max speed override to anything, really. So what I want to do instead though is make two different values and I'm going to call this sprint speed and then I'm going to call this run speed. And the really cool thing about this and the way that it works here is that if I go back to the mover component, a new category has appeared here and these are my blueprint values that I've made in the blueprint movement mode, which are essentially going to override the value down here. So now I can type in, I want my sprint speed to be 500. I want my run speed to be 250. And those values are going to set stuff in here in that generate move function So fingers crossed if this works is okay I running And then if I hit shift now I sprinting just like that And this is replicated as well. So we get multiplayer sort of really, really quickly, which is super great. And then I can continue to do things like, well, I also want to modify, let's say, acceleration based on if I'm sprinting or not. And you kind of can get the picture. Another thing that I can do, which is, I should point out, is important. You can notice that I have a kind of a fixed deceleration parameter here. And let's say that, you know, when I'm running around and I'm sprinting and then I let off a shift, I want to slow the character down slowly. So I might come into the movement mode here, and I want to set deceleration to like 200, let's say, to slow down how quickly the character can slow down. So if I start sprinting and then I let off shift, you can see that I'm slowing down a lot more slowly. Problem, though, is if I let off an input, now I'm taking forever to stop, and that's no good. and so what do I do because I only have a single deceleration parameter well again I can modify these parameters in blueprint in the movement mode that I've created and so what I want to do is I want to take the desired velocity which is essentially you know the velocity that I want to be moving in. And if it is not equal, or if it is, let's say this, okay, so if it is equal to zero, that means that I want to be stopping. And if I want to be stopping, I can set that deceleration parameter to a higher amount like this. And if I don't want to be stopping, I can set this deceleration parameter to a lower amount. And of course, I can promote these to variables that I can mess with them in the actual mover pawn. So let's call this stopping deceleration. We're going to call this one gate change, or kind of like gear change deceleration. all right if i go into here and mess with those values let's see so the gate change deceleration okay i picked up that value is 300 stopping deceleration is 2000 and that means if i hit sprint and then i let go of sprint i'm slowing down nice and slowly to go back to run and if i let off the input i stop very quickly so it stays really responsive um and so essentially with just these values, acceleration, deceleration, et cetera, we can get a lot of really flexible behaviors just based on the blueprint states that you're feeding in through the produce input. There's a couple other values that I want to talk about very briefly. One of those is turning strength. I should have talked about this before. Turning strength represents how fast the character's velocity can change direction. So in CMC, there was this value called ground friction, and that's essentially the replacement of that. So turning strength represents how fast I can go around a corner. So if it's high, I can change my velocity direction very, very quickly like this. But if it is low, then it's going to take me a lot longer to change direction. At least it should, and I don't know why it's not here. Maybe because my deceleration. Wait a minute. I think it's having an effect that just might be hard to see unless I've done something wrong, which is possible. You need quite a low acceleration to really accentuate that, right? Yeah, probably. Let's see. my acceleration is still 1500. So if I change my acceleration to like 300 This is designed to get rid of that sort of drifting effect that you might have when you change direction, right? Right. So here you can see that it's taking a very long time to sort of change its velocity direction. So it's almost like I'm on ice here. And then I crank this value up to like 10. Now I can change direction more quickly. And the acceleration smoothing and deceleration smoothing are still sort of having an effect here. And so all of these values work together a little bit. And so it takes some trial and error, just playing around with it, to get some movement values that work for you and your game. But we believe that it's quite a flexible movement mode that can be taken in a lot of different directions. Or movement model, I should say, is a better term. And so what I've shown here is sort of the base for what we've done in the mover pawn. And we have a folder here called movement modes. And one of those is our blueprint movement mode walking. And you can see here that, you know, same as last time, I'm doing the generate move and doing the parent generate move function, but I'm also doing a lot more. So I'm changing the max speed based on the gate, based on the crouching state, changing the acceleration based on the gate. and if I'm faster than run so that I can get to sprint at a different rate, deceleration, turning strength, and facing smoothing time, which is how quickly the character's rotating. And so you can go in here and look and see all the things that we did. And one of the very interesting things that we did that I touched on at the very beginning of the live stream was all of that rotation offset behavior that I showed So let see if I can show it again real quick here So if I turn on our shapes and our graphs, all this rotation offset behavior, all we're doing here is if I open up the mover pawn, just bear with me, go to the produce input function, and same thing right i'm setting all these structs some of them are the default values or sorry the default structs that's provided and then also we have mover custom inputs which is the user defined struct that we made includes a rotation offset and that rotation offset is what is offsetting the rotation away from the desired facing direction that you're and putting into mover. And that's being done here. And so we're setting an overwritten desired facing value. And this is a Katernian, which are never fun to work with. I prefer rotators. But you know. And then we're feeding that into the desired facing here. And then we're also doing some stuff, which is this came in pretty last minute. But this is sort of clamping the angular velocity so that when you're spinning the camera quickly, the character doesn't under rotate. And so I can demo that here. If you look at the debug shapes down here, if I'm offset at 135 degrees, if I spin the camera quickly, you can see that I'm never, that pawn, which is the small black arrow there, is never going beyond 135 degrees. And so I can spin the camera quite quickly and not under rotate, which is important if you have an aim offset where the character is aiming a weapon and you can't break that. And so that's all being done in this little bit of math there. And then we're also doing things so that when we are changing directions and doing like a 180 degree pivot or a turn, this bit of math is always making sure that we rotate toward the desired facing direction. So if I were to do something like this and then pivot, we're always rotating toward the desired facing direction so that we never rotate the other way around and break the aim. And so even if I'm turning this way and then do a 180-degree turn, typically what you'd see, like if I wasn't strafing, and if I do it in this mode, I'd rotate toward the camera. And so that's just ensuring that we're always rotating toward the desired facing. And I'm probably missing some stuff, but that is a decent overview of this movement mode. I should show off sliding as well. Do you want to show off the 360s? Yes. Oh, yeah. I think I did that a little bit at the beginning. So based on the strafe style here, and we also have another value for aim. And so when I go into the aiming mode, you can see how those quadrants change. So if I'm doing this, then I want to aim a weapon, we can switch to a strafing direction. So if I do just the forward direction, I've got 360-degree spin animations that go like this. And so you can make kind of Max Payne-style locomotion, which is really cool. So there's a good chance that a lot of this rotation offset stuff will be kind of tweaked and modified as we go further. I think it'd be good if everything was contained inside the movement mode. And so how we're calculating the movement direction and offset was all done in the movement mode. But we did a lot of experimentation these past couple of months. So there are definitely things that we want to tweak. But I think the concept will be similar. So that, oh yeah, sliding. Sliding is actually just a modification of, again, the smooth walking mode, because it gives us, you know, the smooth walking mode gives us a lot of freedom to do different accelerations and decelerations, turning strength, etc. And so we've augmented that to become a very nice sliding model. And so what we're doing is we're taking in the normal of the ground, we get a slope angle, and then based on that slope angle, and we're changing the max speed and the deceleration based on the slope. And I should note that it's sort of like the slope angle is determined by your movement direction relative to the slope. And so if you are crossing a slope at like a 90 degree angle, it's almost like you're on flat ground. So yeah, that was a lot, I'm sure. And I don't know, there's probably a bunch of questions. I did want to point out, if it hadn't been said already, like the smooth movement mode and the simple walking mode, those are both in the core mover plugin. So they're not like something special we did for gasp, but the, the blueprinted ones are. Yeah. And Justin talked about like modes that were written a hundred percent in blueprint. And we do plan to showcase that in a future update. That's definitely important to do. So whether that's like a, I don't know, I'm not going to make promises, but whether it's like a zip line or something like that, where we can showcase how to do a movement 100% of blueprint we definitely think that'd be cool to show um one one really minor addition uh to all the stuff that you've just shown caleb um there's one key aspect to have all this work on the ai that i didn't want to miss um so in the main pawn there's a sister component um called the nav mover component uh that if you add that to the character um and then during the produce move in our gather move function here. We just had a branch to say, hey, if we're an AI controller, we need to consume that input. So this is how we get the AI controllers like intent to then pass on to the rest of all the stuff that Caleb is, has built. And so that means that assuming that, you know, the controller setup is good for your AI stuff it will just pass through the rest of the system and it's that straightforward. But the key thing there is that consume nav input a function call. Cause the CMC did that automatically. Yeah. So we have to, yeah, there's definitely more boiler plate stuff we have to do with mover. but again, the ceiling is quite high. I just wanted to mention as well that if you're using motion matching, that's all trajectory-based. And what's great about all these mover modes, like even if you make your own Blueprint, move a mode, when we query the trajectory from mover, it will actually simulate your code, your blueprints, and run them. So whatever logic you're doing in there, it will work for trajectory. as long as you've piped in the inputs the way that Caleb showed. It should just take the current input for this frame and assume that you're going to keep the same inputs, and then tell you what that's going to do. And that's really great. That means that that's very different from CMC, which was we had a function that knew exactly what the CMC did and would replicate its behavior to generate a trajectory. But that meant if you wrote your own custom movement component, like you use the custom mode in there and extended it and did your own stuff then our trajectory prediction just had no idea about that and would not work so this really makes it easier to do motion matching with custom custom movement and i can show that a bit you know if i draw the trajectory here you can see that when i go and slide the trajectory changes like if i try to slide and turn you can see that it has a very different sort of profile and it is predicting into the future as well. So it's very, very powerful. So all of this is essentially being simulated by the trajectory predictor in the animation blueprint. I saw a good question in the chat. Someone's saying, like, why did you do this all in Blueprint and then in C++? I just want to be clear, like, smooth walking mode and the simple spring and the simple walking mode, they are C++ classes. And if you want to write your own custom movement mode in C++, you can totally do that. You can derive from either the base class, if you want to be completely custom, or you could derive from a simple walking mode. And actually, to do the spring one, I think it was like a few lines of code that's just calling some spring functions and returning. So that's a great thing about Mover is it's really easy to describe your movement mode in just a few lines of code or Blueprint. And it will be a common workflow, like at especially bigger studios, like let the tech designers or animators go crazy, craft movement using Blueprints, and then when it gets closer to shipping time, have an engineer come and nativize it and put it into C++. That's right, yeah. And so there's a good chance, again, I don't want to make promises, but there's a good chance that as we continue forward with this project and we find, you know, like a movement behavior that we really like, has all this fancy stuff, it's possible that we could convert that to code so that it would be super performant and just kind of work out of the box for your project. but again the real reason why we haven't done that yet is simply because I need to experiment in blueprint because I can't code so it's like and of course we want to show users you know just give them the flexibility to do what they want yeah so yeah the project is actually a pretty good forcing function for movers development like we had to um do a bit of work to make more things blue principle uh and expand what you could do just because gasp is we were not allowed to have any source code changes um so yeah it's it's been a good project for advancing that aspect of it yeah well first Thank you all so much for walking through all these updates and all the really cool new stuff that's come out with Gasp lately. If you're up for it, we have been collecting some questions from chat while you all have been going through demos. And I figured we could kind of rapid fire through some of them. If you're up for that, I want to make sure. Is there anything else that you want to show first? But, okay. I'm sure we missed something, but that was, what was it? Like almost three hours or something? There's always more. All right, so I figure I'll just ask the questions, whoever wants to pick it up. If multiple people want to chime in on it, feel free. We'll just kind of reform it. We'll go through it. So first question I've got for y'all. Someone is curious if there's already a recommended way to use the new mover with network prediction together with gas in a production setup, or is integration between mover and gas still considered experimental and or kind of DIY? Yeah, we have not solved all the problems there yet. That is something we want to put out more examples of doing. We have certainly done some experimentation internally. But, yeah, there's, I think, probably in the next release of Unreal Engine, we may have something more to show there. that people can follow after pattern after. Yeah. Until that time, like you're going to, you're going to be poking around with it just like we are. I know there are some, some pain, pain points or challenges there. And a lot of it is just like the way replication works, especially. So network prediction also supports a fixed tick mode, which is, which is different than how a lot of the systems like gas work And so you have to put a little bit of effort into synchronizing movement and gas and have them come together at the right times. Like if your gas ability, for instance, is like taking place over some time, we've found the need to basically insert sync points where it's like, okay, the gas ability can't progress any further until it's a frame where movement simulation is going to occur or something is emitted from the movement simulation. But one nice thing I will say, in the past, like when you're working with CMC and gas, I mean, it has its own problems as well, working together, they're kind of racing against each other. So what a lot of folks did for modification there is they would stuff things that could trigger abilities. They would modify CMC and include data bits that could trigger abilities. And that's a way to improve synchronization between the two systems. That becomes a lot easier now with Mover because you can author custom structs in your inputs and in your state structures, whereas it was kind of a heavy lift before. So, yeah. Yeah. Awesome. That's good context to have. Thank you. Next question I've got for y'all is, what's the recommended way to handle the camera while using Lover? I mean, it's not really any different than anything else. I'm not sure. Yeah, the camera system is still a separate thing from Mover. I'm trying to think if there was anything that came up during... No, we didn't really make any modifications to the camera system. Though I do want to share something that I didn't share before. So if I can take my screen share back, I think it's important information. Yeah, absolutely. We have essentially now that we're dealing with like multiple characters and multiple animation graphs, multiple systems, et cetera. We felt the need to, we're sort of forced to create some interfaces which are passing data to the animation system and to the camera system. And so if I open up the mover pawn here, there are some interfaces. This one is just the sandbox character pawn interface. And this interface has some functions to get properties for the camera system and the animation system. So if I open up, well, let's start with the animation system. If I open up that, we can see that I just have a big struct, which is all the data that the animation system needs to know. And some of that data is being retrieved from Mover. And something to note here, which I think is also important that I forgot, is that we have two different sets of these structs here for Mover. We have pre-sim and we have post-sim. And pre-sim is basically the values that we are sending into Mover. so that it can do its update. And post-sim are the values that we are getting from Mover after it's done its update. And we are using these values, the post-sim values, to drive the camera system and the animation system. And these values will be replicated. We are doing that here. We're just caching those inputs from what we've received from Mover. And so you could do this every single time you want to get that value, but that's just a lot of noodling around and, you know, we just wanted to cache that. The other thing I will say quickly, which might come up with a camera system, is that the network prediction plugin sort of has a bug where it forces the tick rate to be, well, essentially it forces mover to update before the pawn. And so right now in GASP, there is a one frame delay between the input and movers update because movers happening at the beginning of the frame. So mover updates, and then your input, and then the animation systems, and then mover. then the next frame mover gets those inputs from the frame before to do its move and so you have to be kind of careful right now with how you're driving things but again because we've done this sort of post sim value as long as we drive our animation system or our camera system with that it will be accurate to mover it will be in sync with mover so still a frame behind like your enhanced input actions, but in sync with Mover, which is important. That was a long answer to a simple question, so I apologize. It's good context. All context is good context. All right. Trying to get all the Mover questions kind of in one. Next question here for y'all is, is Mover networking good enough now? So if we were to use network emulation, there wouldn't be a de-sync happening um seems like this person was maybe experiencing that with like cmc and bp yeah i mean i i always test with network emulation on otherwise it's not a good networking test uh yeah every everybody should always use that uh as part of the regular development flow um it is it's good enough for it kind of depends on the on the scale of things like basically the more characters or replicated objects you have, the more sensitive it will be to poor network conditions. The network prediction plugin itself is still a bit immature in some cases. There are bugs where, you know, if you hit a patch of very long latency it will never recover to be back in a mode where it assuming there low latency That's something we're working on fixing in the near future. And you'll also start to get warnings about if you don't receive updates for a SIEM proxy in a timely manner, you might see stuttering movement stuff like that certainly you'll see warnings in your logs for sure it's not as robust as it could be and yeah that's just something we're working to improve How does it compare to CMC? That's where a lot of people are coming from Well, CMC is a little bit different because each client, well, there's two different modes, right? So network prediction has a regular, I would just call it regular independent mode, which is similar to CMC, where each client is driving its own movement simulation at its own rate. so that's exactly how cmc works um if you are using if you go to like a fixed tick mode then you every client is just trying to get its inputs to the server on a shared timeline like the server is going to simulate no matter what uh at a at a certain time and if the if the inputs arrive rate, they will be consumed. They would get buffered and consumed. If they arrive late, server doesn't really care. Server keeps on trucking with maybe the last input it received or starts to decay the last inputs. If you're having a laggy client, the client is supposed to adapt to that latency and try basically a high latency client will try to predict farther ahead of where the server is where somebody with super low latency does not have to predict so far ahead and it's supposed to kind of accordion as network conditions change but yeah that's it it currently does the first part which is adapting to worse conditions but it does not uh does not yet shrink and i would i would consider that like part of production readiness awesome thank you uh i think i'm going to toss one more mover question at y'all and then i'll uh poke into some of these other topics last one for now is will there be blueprint support for Mover shared settings. Looks like someone tried to make one in Blueprints, but it gave them a compilation error. Like creating them from scratch, I guess. Maybe that's the question. I'm pretty sure we've extended them or overwritten values on them. Yeah, that's not... I guess that hasn't really... Creating one from scratch has not really been on our... our roadmap but uh i will add that to the i'll add that to the hopper is something we should look into awesome all right next question i got here for y'all um someone's curious what workflow would you suggest to easily update gasp over updates like if they're upgrading now to this new one that just came out if you have a recommendation for that process uh it is a difficult process right now we're aware of that there's definitely been tons of requests about you know making a plugin version and internally we've had conversations about well you know how can we provide this as a plugin rather than a standalone project and there's just been technical hurdles that have come up that have put restrictions on the way on the ways that we could do things that we didn't want to deal with at the time and so it's on our radar to make that easier in the future as long as we can not put restrictions on, you know, kinds of things that we're doing in the project. So right now, you know, we'll have to migrate the content in the project over to your project. And then anything like console variables that we've added to the project settings, you know, make sure that those come across as well. And then any plugin dependencies this project has that you have to have in yours as well. So being that it's blueprint only, the migration process should be relatively smooth. But, you know, that is kind of just the reality. And of course, with updates over time, you know, we are trying to constantly develop new techniques and new things. And if we are tied too much to what we've done in the past, then that can limit future development. We're hoping that every update is not going to be a completely different thing and a completely different way of working. But there have been times where we've had to change how we've done things just to make it better for the future. So I think the project is in a good place now. We've got some interfaces stood up. We've got some other things that, you know, in future updates, the overall structure of the project shouldn't change all that much. And again, like I said, we're going to be moving forward with the mover pawn, which is a little bit more modular in nature. And so if we make changes to the movement modes, et cetera, you should be able to like pull those over. So. Yeah, that's awesome. Next question I've got for y'all. So I was curious if it is possible to have analog speed and gradually accelerate from walking to running to sprinting. Okay. I'm glad. I want to share my screen one more time. No, this is good. This is what we're doing for. So analog speed is quite tricky, actually, to do correctly. I know that sounds ridiculous but it can have a lot of weird effects on things like animation selection But one of the things that I did do I think like a couple of days ago before we shipped this thing is I added a new setting here for the mover character for analog input style. And so we have a single gate or we have walk run. And so if I'm in the walk run mode here, if I turn on a controller debug, if I push the input a little bit, I'm in my walking gate, and I'm pushing the input all the way, I transition to running. It's a little bit different than fully analog speed control, where, you know, you are gradually changing from like your no speed to like your run speed or something like that. It's almost like gears on a car, right? You're in your slow gear or your fast gear. Those gears have discrete speeds. But, you know, because mover is blueprintable, like we've shown, there's definitely ways in which that can be done. But for animation style that we were going for, where we have a walk speed and we have a run speed and we have transitions between those, it made sense to stick with the two different gears and then just like select them based on, you know, like what I'm doing here is I'm just selecting which gate I should be in based on how far the stick is pressed. the animations are built in such a way that you could use analog motion i've done them in phase and stuff like that so they will you can drop them into a blend space and then select in between and stuff like that their styles work in such a way that it will work um that being said there's a lot of animation things that come into fact when you start doing analog motion it's more of an older way of doing things older games did it because you could have a lot fewer animations to have these things. But then a lot of things get really weird. Like your stop animations become really weird because now your start speed and acceleration, we don't know what they are because it's whatever your stick deflection is. Same thing for stops. And so that's why, and you think about those older games that had that very analog motion where you could just push forward slightly. You could do those little tiny little steps. There was never like a little tiny step stop animation. You'd have to then make, you know, infinite amounts of stop animations to work for all those different speeds. And so then you have to generalize your stop animations to make them work for multiple speeds, which we didn't do. We just went for gears on a car where it's like you have a walk speed, you have a run speed. And it's kind of a newer way of doing things now where you create the animations for it instead of trying to rely on a cross-blended motion. But it is something that we could probably explore in a future update. Again, I remembered when we were polishing this project, like, oh, yeah, that was definitely a request and we haven't done that. So let me see if I can squeeze it in. So I did fly that kind of under the radar. So, yeah. Nice. Awesome. Well, I know that there are additional questions. I feel like we could realistically sit and talk about GASP for several streams over. There's so much here to explore and to dig into and to learn about. Um, so we'll probably call it here for today just for our poor guests. Thank you so much for, uh, taking all this time to sit here with us and go through all these cool things. And also thank you everybody who came to watch the show because it's for you. It literally wouldn't be what it is without you being here, using the tools, asking questions, being part of this whole process with us. So also thank you all so much for being here. Um, if you do have any other questions about the update to GASP about any of the new plugins or features or stuff like that, as always, you can leave comments under the video here. We'll collect your feedback. We always love to see what you're doing and hearing what you have to say about all this stuff, how you're utilizing it, cool things you've been enjoying, things you think could be done better. All that good stuff is important to us. So please let us know. If you popped into the stream partway through and you missed some stuff or you just want to go back because there was a lot to review here, no worries, because we post all of our streams in video format that can be viewed on demand on both our Twitch and YouTube channel at Unreal Engine. You can also keep up with us at Unreal Engine on all of our socials for the latest news, updates, all that kind of good stuff. And then last but certainly not least, if you haven't already, please come join us over on the Epic Developer Community. That's where we have everything like our documentation, tutorials made by Epic staff, plus wonderful community members alike, as well as the forums, and pretty much really kind of anything you need in regards to the engine most of it you could find there so i might be biased but it's a pretty good resource so go check it out if you haven't already um a couple last notes again keep an eye out for the uh fun little look into the tarantino stuff next week and also we will be doing a stream our annual in fact end of year year and review live stream with tim sweeney as well as some of our other leadership uh next thursday we're all going to be dressed up to the absolute nines and like the most ridiculous over-the-top holiday get up you've ever seen in your life it's going to be great you gotta be there um so with that i want to give one last big thank you to the guests is there anything else y'all wanted to let anyone know before we wrap up for today and i finally release you back to the rest of your days have fun i yeah it's experimental so you know i'll just say that right we're yeah there's gonna be things that i'm sure you wish were done differently and that we wish were done differently there's definitely stuff there too um so uh but again you know we're gonna be constantly improving this yeah absolutely yeah and share your creations. It's good to see what people do with it. This is a starting point. Give it to the community. That's right. Absolutely. Yeah, there is so much to explore. The link to the project is available in the chat. We'll also have it linked in the description in case you're watching this as a VOD later. So go download it, go play, go have fun, and we'll see y'all later. Thank you so much, everybody. Have a fantastic weekend. Bye, everyone. Thanks, Tina. Thank you. Yep.