Unity Starter Assets In-Depth Overview | 1st & 3rd Person Controller w/ Input System & Cinemachine

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today i'll be going over unity's new starter assets i'll be going over the first person controller and the third person controller i'll be giving a general overview of each one going over the project showing you how to change the settings i'll also show you how to enable the mobile mode for each one of them so you can use touch screen and after that i'll do a deep dive into the code so that you can understand what's going on in the back end and i'll also give some suggestions on how i didn't prove it so before we start we actually want to add these assets to our project so go to these two links here which i'll have in the description or you can go to the unity asset store assetstore.unity.com and search up starter assets and if you scroll down it'll be this one the third person and the first person so once you open up both of them you can just click add to my assets and it will add it to your assets that now we can access in unity now before we begin i just want to cover that the starter assets recommend 2020.3 long-term support which is lts however i tested it with 20.2 and it worked but if you're making a full game you should use lts just for the stability and so what's cool about these two projects is that they use the new input system and cinemachine so it's good to see some input system support and it also has support for the built-in render pipeline as well as shader graph alright so i'm just going to make a new urp project just to show you how it is so once you have a new project opened you can just go to window package manager then under here you can go to my assets and then you can select sort and do the purchase date with the arrow pointing up so that we can see the newest purchased assets or you can search it up here in the search bar and let's start with the first person controller so i'll show you how this project is so down here you can click import and then import again and now it will import the whole project into unity as well as the new input system package and cinemachine for you so you don't have to have those packages downloaded prior to this click yes here it will restart the editor to apply the new input system all right once this has loaded we can exit out and now here under assets go to starter assets first person controller scenes and let's click the playground so you see it's ping here and the reason why i chose urp or universal render pipeline was that i can show you how to fix this if you're using the built-in render pipeline it'll just show up normally so to fix this we can go to edit render pipeline universal render pipeline and then upgrade project materials to urp materials and proceed make sure you have a backup of your project before doing this proceed alright and now it'll fix all of the materials and now it's compatible with urp alright now that we have that set up quick thing that i want to mention if you go back to the scenes folder and go to playground this reflection probe when you drag and drop it into the scene it makes the scene look much more brighter and it's because it adds some sort of reflective material to the environment all right so now to show you how the project is i'm just going to go to layout and tall so it's easier to see put the game at the bottom so if i put maximize on play and play you can see that we're now in first person mode and we can jump we can walk if we press shift we can sprint we can also go up the stairs and this is using the character controller which is pretty easy to go up the stairs if you just add that or you can just jump off and yeah it's a pretty simple scene but it just shows you what it's capable of all right so if i go into the hierarchy let me show you how this project is set up so this is using cinemachine the player follow camera is the cinemachine virtual camera and so what's in the machine is it's a virtual camera that basically instructs the real camera on how to move so we have this virtual camera with certain settings in this case we are following this game object which if we double click it it will take us to a root under our player which we can double click this is our player and we have a root under it which i'll explain why we have that in a second and so with cinemachine you have this follow and then you have this lookout property in this case since it's first person we don't need to look at anything this would be more for a third person point of view but we do still want to follow our player and then for the body which basically instructs the cinema machine how to move we have this third person follow even though it's not third person we can use third person follow and then put a camera distance of zero so that it's right centered in the middle of the character and you can see if we increase the distance it'll zoom out from the character and then ignore tag basically ignores the player game object as you can see if you hover over it says obstacles with this tag will be ignored it's a good idea to set this field to the target which is our player and so here are some settings you can just adjust for the aim this is corresponding to the lookout component which we don't currently have anything so we can just put to do nothing noise basically adds some random noise to the scene so if you do stay still for a while you'll see that the camera slowly moves up and down as if the character is breathing and that's the noise in this case it has a handheld normal mild and you can pick whichever one you like add some offset amplitude and frequency amplitude is how much and frequency is how often and so this virtual camera instructs the main camera through this cinemachine brain on how to move so you see we have some settings here that you can change if you'd like and if you hover over these it'll go more in depth on what each of these does so for example these two are for blending between different cameras here you can specify how it blends in and blends out of a certain camera and i do have a whole video on this if you're interested and then we have our player so our player has a character controller which makes movement pretty easy to implement it has a min move distance of zero so this is important if we want to move correctly ideally you should always have this at zero for your player because if the character tries to move below that value it will not move so if it's jumping this can sometimes mess it up then we have our first person controller script and this is the actual movement code and jumping code and we have some settings we can adjust here you can adjust how fast it moves how fast it runs which this is with shift how fast it rotates when we look around this is used for acceleration and deceleration which i'll go over the script soon this is how high the player can jump gravity how much time the player needs to wait before jumping and you can actually hover over these and it will tell you what each one of those does and so here for grounded this is for collision detection with the ground for the layer it's set to default because in this case the ground is set to the default layer and we're checking against that layer we also have the cinemachine camera target which this is actually used to rotate this in a machine camera so the first person controller rotates this route depending on the direction that it's facing and then this is what's getting fed into the cinema machine follow so the cinemachine follow will rotate as the character rotates or as the root of the character rotates now we have this basic rigid body push which is pretty cool so you can push objects for example if we select these two cubes here we can give them a new layer add layer let's name this layer to push and now let's assign that layer to those two cubes and we have to make sure to also add a rigid body to be able to move the cubes or push them back to the player in this script we can specify a push layer in which we want to push objects and we can select can push so once we get near these cubes we can now push them pretty cool and these are what actually drives our input so this is the new input system and the player input component basically takes in an input action asset and that's where we define our controls so if you double click this you see that this pops up this is an input action asset and this defines our controls so our action maps are a set of controls in this case it's named player the actions are the actual control groups so for example we have a move group and under move we have two different actions that can perform this move so the move is a vector 2 because we're moving with the wasd keys which you can see here if we click here there's two bindings up down left and right wasd up down left and right up arrow down arrow left arrow and the right arrow and we also have a left stick for the gamepad so any of these two actions will execute this movement for the look it's very similar instead this is using a mouse delta or a pointer the pointer can be a mouse or a pen and the delta is just the change in position between the previous and the current frame so we can tell the direction the player should look in and the right stick for jump we can use the space or button itself on the gamepad and for sprint we can use left shift on keyboard or left trigger on gamepad so the player input component basically takes in the input action asset and wraps it with other behaviors to make it easier for you to use for example it has this auto switch properties so if you're using keyboard and then you switch to gamepad then it'll automatically switch the control to gamepad but if you deselect it it won't allow you to switch it and you can also select the map that you'd like these options are more for local multiplayer where you have more than two players and need to assign a ui and a camera to this input component which i have a video on and then this script the starter assets input actually manages the input so it reads these values from the player input and stores them and then the first person controller script reads these values from the starter asset's input so think of this as an input manager and the way it gets values from the player input component is that you see in the player input component it has this behavior called send messages so send message will call certain functions on each of these components in this game object in this case it'll call all of these functions on move on look on jump on sprint and all you would have to do is in your script on that game object you can just have a function defining on move and take in an input value value i don't really like how this is done though because this calls it on every component in the game object even though we only really need it on this one so i'd recommend to actually use invoke unity events which from there you can actually drag in your script and you can call the certain function that you want to call on it however i'll go over that in a bit all right and last thing i want to mention for the first person one which also applies to the third person is that you can enable the mobile mode so in this ui canvas starter assets joysticks you can just enable that and you'll see it'll pop up and it nicely scales with the screen because it has this canvas scaler component on the canvas which scales with the screen and if you open that up you'll see that each one of these game objects has a rec transform which is a ui component and it's anchored to a specific location as well so when the screen moves it will stay anchored to that corner in this case it's the left corner so the way they did it is that they made their own joystick script and it takes in a container and a handler so if we open this up this is the container which is the big circle and then the handler is the little circle which we can move around and this is what's actually going to be moving the handler the handler will be moving within the bigger container and you can set the range here of the joystick and how much you want to multiply it by you can also invert the x and the y so in this case if you invert the y if you put the joystick up then the character will look down and for the button they just have this virtual button script and so for the joystick and the button what it does is that it sends out an event with the input and then the parent canvas is actually listening to these events with the ui canvas controller input which all it is doing is taking in the input from the joystick and button and calling the starter assets input script with that input which if you remember that's under the player and that's what manages the input from the player input so it also manages the input from the joystick and so to test out the joystick in the editor we actually need to go to window analysis input debugger then under options you can put simulate touch input from mouse or pen so it kind of acts as if we're on mobile even though we're in the editor and if we click play unfortunately you'll see that the joystick kind of gets stuck and our cursor disappears so two things we need to do under the player capsule under starter assets input unselect cursor locked and cursor input for look since we want the cursor not to be involved in the actual input we would just want to use it to simulate a finger touching the screen and for the ui event system this is using the new input system so it has this ui input module for the new system we actually have to change the pointer behavior to all pointers as is for it to work properly and i think this is actually a bug with the input system but this takes all the pointers without processing and this one processes the pointers and tries to group them together if it detects multiple at the same time if it is a mouse or pen and i think it just creates some bugs and so you can actually see this in the documentation all pointers as is it doesn't matter what's touching the screen it just is treated as its own pointer whereas this one if it isn't a touch screen it's treated as a single unified pointer so if you don't change this it's not going to work in the editor and you can see if we move around the joystick the player will move around and look around it'll also jump and if we move around which i can just move with the wasd keys we can also sprint so it can go a little faster cool so that's the basic overview over the first person controller from the starter assets i'm gonna go over the third person one now which is kind of the same thing except the only difference is the animator where they animate the player so if you can just go to window package manager sort it by the purchase date and you can just download the third person character controller and import it just as we did the other one import it into your scene all right you can exit out of the package manager and if you go to starter assets now we go to third person scenes playground for some reason all the assets got replaced so we can just go to edit render pipeline urp and upgrade proceed and then i'll go to the playground folder get that reflection probe and you can just drag it onto the scene to change the lighting a bit all right so now we press play you'll see that this is very similar to the first person one the only difference is the camera distance and the fact that it animates so it blends between an idle and a walking animation now you can jump so when you jump up it has its jumping up animation and then it has this landing animation you can sprint and it will blend the animation faster and yeah this is basically the same thing just with a different angle it moves pretty well one thing i want to mention is that in the game view you see the screen very small make sure to uncheck low resolution aspect ratios right under free aspect so that it looks normal see if you have it checked it looks small all right and so you can see that we click on the player it's the same thing everything's the same the only difference is it has an animator which i'll go over in a bit and the difference here is the camera now has a camera distance of four and they have a little bit of a camera side offset so back to the player if we click on the animator tab here which you can go to window animation animator as well this is how it should look so you see that we start here and then we have this idle walk run animation and it's a blend tree so it blends between these different values so right now if it's zero it's idle however if it goes to three you'll see that now it's in the middle and if it goes to the maximum now it's running so it depends on the speed of the character and you can see the thresholds here it's actually two for walking and six for running set it back to zero so we're in this state and then if we jump which this is a trigger then we play this jumpstart animation once that's done it goes over to an in-air animation which you can see it has an exit time here so this one transitions to this one once this one is finished then from here we go to the jump bland animation and this is only triggered if it's grounded so once it has reached the ground then play that landing animation and then it goes back has exit time to the main one and from the main one if we fall off of a cliff or something you can go directly to the in-air animation if we have this free fall trigger set and of course you can do the similar thing you can have these joysticks and you can make sure to disable these mouse settings here as well as have the event system be all pointers as is and then now we can move with the joysticks similarly awesome all right and now that the general overview is over i wanted to go over the scripts a little bit so that you can really understand what's going on and if you need to make some changes for your project you can easily do so because you understand the script so i'm going to start with the most important ones which are the starter assets input and the third person controller so i'm going to show the third person script it's almost basically the same as the first person one the only difference is that this takes into account the animator component and plays animations but the concept should be exactly the same so if i right click the starter assets input all this is doing is having these functions that are called from the player input component with the send messages right here the behaviors and messages and then it calls these functions so it doesn't actually do anything in these functions it just kind of pipes that input into these functions because these functions are also called from the joystick ui so in the ui canvas controller for example all it is doing is calling these functions directly since it doesn't have these values these input values so these are just used for the player input component while these are used for actually setting the input to the variables so yeah this is basically all the script does it just sets the input to the variables and then if we go to the third person controller edit script we can see a lot of stuff going on here these are the inspector values that we saw previously and it explains what each one does here are some private fields that are set in the script i'll just go over the script and that will explain these variables soon alright so in the awake function we get a reference to the camera which i totally don't like how they do this first of all we don't need to check if this is null because obviously it'll be null when the game starts so you can just delete that if null check additionally they're using find game object with tag when we can just do camera.main instead because it's used for that and you can see that the main camera they actually use a game object even though if you go in the script you'll see that it only uses the transform so instead of game object we can just set it to transform and here camera.main we can do camera.main.transform and if we go to where this is being used then you can just delete the dot transform here so this is the first person controller and you'll see that they have this code here and they don't actually use the main camera anywhere so you can just delete that entirely in the first person one then in the start method what it does is that it gets this animator component attached to our character it doesn't have to have an animator component because it does the try get component so it will return false if it does not have that component and we get a reference to the character controller and the input manager and if you go up here it actually requires you to have the character controller and player input manager attached to that game object and if it doesn't if you add the script to a character it'll automatically add those components for you and then back to the start it's just setting these timeouts which here it determines how long we have to wait for it to jump again and this is how long it has to wait before falling and this is more for like when you're falling off of stairs or falling off of a cliff of some sort in the update method here you see that it tries to get the animator component on every frame i don't know why we literally did that right here and you should not try to get a component on every frame so you just delete that i guess that's if you just decide to randomly delete the animator while you're playing the game but that doesn't really make sense then here in the update they do jump and gravity then ground check to see if the player is grounded and then the movement code which here i actually put the grounded check before the jump and gravity so that the jump has the current grounded state instead of the previous frames grounded state and then in late update which runs after the normal update we have the camera rotation code which you should put camera code in late update the assign animation ids basically take these parameters in our animator and just sets them to an integer here so that we can easily access them in this script and we don't have to keep accessing them through strings so here is how they're doing the grounded check and it's just using a sphere offset from the player in the y direction a little bit down so for example we're using our current x and our current z and for the y it's our current y minus some offset and then it's just using physics check sphere with this position along with a set radius and a set ground layer and it's also ignoring triggers so in the ground layer you can set what you want your ground to be before i continue another thing i want to mention is that this is not following correct c sharp standards this should be camel case for all of these variables move speed instead of capitalized move speed which it's funny because in their other scripts they actually do it correctly such as here so i'm not sure why these scripts are different from the others so if you want to follow normal standards you would put this as camel case for all these variables and i definitely recommend not making any of these public because these don't need to be public so i recommend making these private and then if you want to see them in the inspector just add a serialized field and you can change them in the inspector just as the public but the public basically opens it up to any script can access this and change it all right back to the regularly scheduled program under the grounded check if there's an animator component then set that boolean grounded to our grounded check and cool thing is that if you go to the scene view you can see where the grounded check is taking place by this green sphere here so you can see that it's checking within this sphere if it's grounded and that's actually down here on the on draw gizmos which what it's doing is drawing a sphere similar to how we're doing the grounded check and it's drawing it green if it's grounded and red if it's not grounded here i'd recommend storing these up above since we don't need to be setting these every frame since they're not changing all right so that's the grounded check i'll go over the rotation later i just want to go over the move and jump first so the move which is actually after the jump but in this move what it's doing is that here is it sprinting if it's printing use the sprint speed else use the normal movement speed but if our input is zero set the target speed to zero this takes the current velocity of our player and gets the length of that vector so we can get our speed here we're setting some speed offset which you can do it up here since that value isn't changing you can just add it similarly to how they do it here private cons float and set it there instead of on every frame if it's using analog movement which basically means floats from zero to one with all the values in between then we can select that magnitude else we do one if it's not analog it's digital and digital is full numbers like integers zero or one there's no in between so that's why it's either the magnitude or one here basically it lerps to a certain speed if we're not there already so if our current speed is less than the target one minus the offset or our current speed is larger than the target with the offset then we lerp to that value so we alert from our current value to the target times the input magnitude which is declared up here and we do it times the speed and time delta time and then here this is a cool little math trick that they use to round to three decimal places because for example if you have point one two three four and then if you times that by a thousand that's 123.4 since it goes three decimal places to the right one two three and then if you round that that's 123 and then if you divide that by a thousand imagine there's a point zero here then this decimal place moves three to the left 0.123 would be nice to have a little bit more documentation there for that speaking of documentation none of these are capitalized and none of these have periods at the end which i really don't like so if you're like me you should capitalize it and then here else if we are at the target speed just set the speed to the target speed already now here is the animation blend which this isn't in the first person controller and this basically is for the idle to run animation for the blend tree so it learns from the current value for the animation blend to the target speed times time dot time time speed then this part is a little different for the third person controller but it's basically rotating the player depending on the movement so if the movement is not zero then we're going to use the a tan two function with our input direction times it to degrees and then add it to the main camera euler angle so basically what this does is it takes the current main camera angle direction the y is the way we're facing for example we rotate on the y you'll see that it moves sideways so we're taking the existing one and then we're adding our input to it with degrees and you can see the a tan two function all it does is basically determines the angle between this axis and our vector so that we can get the angle and rotate it accordingly and then it does this smooth damp function from our current angle to the target rotation it stores this rotation velocity and this is like the speed rotation move time and then it sets the transform rotation directly through quaternion.euler and it sets the rotation to the rotation we just calculated and so that's nice but we actually have to move the player so this determines the direction that we're gonna move the player in so in this case it's getting the current direction that it's rotated in and timesing it by forwards so this will give us the direction that the character should move in forwards for example if it's rotated this way then it will times it by forwards and then the character will move in that forward direction and here if it's using the animator then set the blends of the animation and the speed and just want to mention in the first person controller it's a little different they don't do all of that it's just right here they just do if the movement is not zero then this is how they calculate the direction to move in which is just taking our current right timesing it by our movement x and then adding it to the transform forward times the movement y so this is how you can actually move the character with your input and take into account their current direction all right and now in the jump end has gravity function if we're grounded reset the fall timer because we're not falling if there's an animator then set these booleans to false i don't like how they're setting these to false on every frame with a state machine of some sort this might have been a little easier done not having to do this every frame we also make sure our vertical velocity is negative two which you can declare up there instead of setting this on every frame since this is constant not changing this is the jump code so if we're jumping and we're allowed to jump the timeout is done then do some fancy maths this is the physics equation and set the boolean animation to true and if there is a time out for the jump then just decrease it over time since we're grounded else if we're not grounded we're in the air we can reset the jump timeout timer so that when we land we have to wait a while before jumping again then we can decrease the fall timer if it's greater than zero so this is how long we have to wait for it to fall and if it is falling if this is done then we can set that animation and then here if we're not grounded then it sets the input manager jump to false on every frame which i really don't like how it's changing the input manager and this is the issue with these public fields is that now this script just because it wants to it can change this value even though it really shouldn't be interacting with the input manager in this way the third person controller should just be reading the input and not actually changing the input so i definitely recommend separating this and not doing this and i'll show you how i did it in another script just to give you a better idea and here it says if our current velocity is less than terminal which is 53 in our case i don't know how they got that number but basically if it's under that velocity then times it by gravity another time so that it falls faster so basically if we're under this terminal velocity then it will fall faster over time all right and then lastly we have this camera rotation function which all it's doing here is taking our current look input the square magnitude which is easier to compute than the magnitude so we don't have to square it if it's greater than some threshold and the camera's not locked then we just set a target yaw and a target pitch the yaw is the y and the pitch is the x so you can see when you pitch a baseball you pitch it from up to down and the yaw is how we're moving rotating our player so the yaw is with our x since we're looking sideways and the pitch is with our y since we're looking up and down and so we want to clamp these values to make sure it's limited to 360 degrees and in this case it's setting the pivot which the pivot is under the player it's called the player camera root and that's what the cinemachine camera is following it's basically changing the rotation of that the x is the pitch and the y is the yaw and it has this camera angle override if you want to set up here i just want to mention the first person controller it's a little bit different what they're doing here instead is that for the pitch which is the up and down movement of your mouse they are changing the pivot rotation just as the third person controller but for looking left and right they're actually changing the transform of the character directly instead of the pivot since in the case of first person we want the player to rotate as we're looking but in the case of third person we don't want the player to rotate depending on where we're looking and the clamp angle just clamps it between 0 and 360. and so that's a basic overview of the controller script i'm going to quickly go over the other scripts just so you can get a basic idea for the basic rigid body push all it's doing is that on controller hit with the character controller it's calling this function if it has a rigid body and we're allowed to hit it it's not null and it's not kinematic then we continue this uses bit mask to determine if we're on the correct layer in this case if we set it to five it's one left shift five times which is 32 two to the fifth power is 32 which is one zero zero zero zero and this basically does an end of the body layer mask and our layer here that we're comparing it against and if it's zero so if there's nothing alike then we'll return if it's not zero that means it's the same layer this checks to see if the object isn't below us then we push it in our moving direction and then we add a force with impulse and our strength here once again i recommend making these private and serialized field in the ui canvas controller input which i briefly went over is just taking in that input from the joystick and the buttons and calling this starter assets input which again private serialize field with this script do you remember when i showed you the auto switch on the player input well apparently that's really bad on mobile we don't want to be checking for auto switch on each time it's very costly and so this basically determines if we're on mobile and if we are we can disable auto switch manually and then here are the virtual buttons and joysticks so for the button all it's doing is on pointer down it's setting it to true on pointer up setting it to false and this function just basically calls that ui canvas controller input the joystick is a little more complicated when we press down it starts this on drag function and it basically takes the position that we're currently pushing on the screen and maps it to our ui with this rect transform utility screen point to local point in rectangle function then it applies this size delta so if we go down there this makes sure that it's in the container doesn't go outside the container and this multiplies it by the difference in size between the container and the handler so that it scales the movement accordingly then it clamps the values it applies the inversion filter that i mentioned and then it outputs the value to this canvas controller which is listening and we update the position of the handler finally there's this hidden script ui virtual touch zone which you can also remove these using statements that it's not using similar to the other ui virtual joystick and button and so this is similar to the joystick alright so i've added a test one here it's basically the same as a joystick instead it uses the touch zone script and it basically makes the handler image disappear and it only appears once you click it and you can't even drag it around not sure why you use that but it's there so yeah it's a basic overview of the scripts i hope you found that useful one thing that i do want to mention that i do recommend that you do is that i really don't like how they change the input manager from the player controller so i recommend in the player input component here instead of using send messages use invoke unity events and so i've actually done this in this test scene that i've made for the first person controller which is the same thing under the behavior invoke unity events and then under events and player i attached the starter assets input script there and called an on move on looking on jump function which you can see here i've changed it a little so now instead of an input value it takes an input action callback context and now it's doing dot read value instead of dot get for the jump it's using value.action.triggered so this is true on the frame that the action was triggered or pressed and for sprint since it's not really a triggered kind of action i'm just reading the flow directly and if it's equal to one then we pass in true and i've changed it so now it's private and i've made some getters here so you can get the values instead of accessing it directly from here so in the first person controller for example the look is now input.getlook move is input dot is printing input.getmove this is just to give you a rough idea and you see how i'm using camelcase here and everything and also added comments to the functions and to show you the jump here i've removed that override entirely where it was setting the input jump to false and instead here we're saying if it's grounded if it's jumping then jump which you can see the difference here this is the original and this is the updated one it's very similar just using as jumping but in the else statement here we're not setting this to false so yeah i hope you all really enjoyed this video it's finally nice that unity is focusing on the new input system a little bit more however these scripts can use a little bit of work especially compared to the old system script which is much better documented and follows c-sharp conventions properly but it's nice that this is a drag-and-drop approach into your project so you can easily get started especially useful for jams and stuff so yeah i hope you enjoyed it thank you so much for watching if you did like it please be sure to like and subscribe and i do want to thank my patrons for the support they help make these videos possible and so with that i'd like to thank my new patrons in the enthusiastic tier we have michael zuhal evan king of limbs chaora and dutch chris thank you so much for the support i really appreciate it y'all make these videos possible and if you're interested the link is in the description i offer source code early access and an exclusive discord channel and if you haven't already joined our discord be sure to do so it's in the description you can chat post memes or ask questions so thank you so much for watching i hope you enjoyed and see you next time [Music] you
Info
Channel: samyam
Views: 12,236
Rating: undefined out of 5
Keywords: starter assets, unity first person controller, unity third person controller, unity third person movement, unity third person camera, unity starter assets, unity new starter assets, first person controller, third person controller, free unity assets, easy character controller unity, unity each character controller, First and Third Person Controller, starter assets overview, in depth starter assets, new unity starter packs, unity starter pack, starter packs, unity starter
Id: CD0FlqllfIE
Channel Id: undefined
Length: 36min 21sec (2181 seconds)
Published: Sun Jul 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.