Genshin Impact Movement in Unity | #7 - Adding the Player Camera

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
With that, we've got the base of our Movement done, but if we take a look at Genshin Impact, we quickly notice that this  isn't how Movement works there. Not only does the Player rotate  towards the Movement Direction, that Movement Direction is relative  to the Camera and not to the Input. If we press "W" to move forwards, we'll always  move forwards towards where we are looking at. That also means that if we  press "S", we'll move backwards, or to the opposite of where we are looking at. To be able to do the same, we  need to create a Camera System. Thankfully for us, we're going to be using  "Cinemachine", which easily allows us to add one. This seems to be what Genshin Impact uses as well. We've already downloaded it  when setting up the project, so we can now easily create our Camera  by right clicking in the Hierarchy Window and going to "Cinemachine > Virtual Camera". I'll name it "PlayerCamera". While I was able to somewhat replicate  Genshin Camera with a "FreeLook" camera, there was a missing option that we would  need to add ourselves and apparently "Virtual Cameras" are more performant as they  only use 1 rig while "FreeLook Cameras" use 3. To start off with our Camera, we need a  target for the "Follow" and "Look At" fields. "Follow" is the target that  our Camera will follow around. "Look At" is the target that  our Aim will be relative to. By "relative" here, I mean that the center  of our Aim will always be on the target. To add these, select our "Player"  Game Object and add a new child Game Object named "CameraLookPoint". I'll add an icon to this game object so  that we can easily see where it's placed. Then, I'll make its "Y" axis be at "1.4". When that's done, we'll set our  Camera targets to be this new object. So, back into our "PlayerCamera", drag this new  Game Object to the "Follow" and "Look At" fields. Note that Cinemachine should add a Cinemachine  Brain to your Main Camera automatically, but if it didn't, make sure you do it yourself. This simply makes it so Cinemachine  Cameras can control your Main Camera. Our Camera is now looking  towards our Camera Look Point, but it's still using the old Input System, so our current mouse Input won't work. Thankfully, it's quite simple to  swap it with the new Input System, as all that we need to do is to add a new  component named "Cinemachine Input Provider". This component accepts an "XY" axis, which will represent the camera rotation and a "Z" axis, which will represent the distance. Of course, to assign an Input  here we need to create it first. So, go ahead and open the Input Actions Window. In here, lets first create a new  Action for our mouse movement by pressing on the plus (+) icon and naming it "Look". For our types, we'll have it  be a "Value" of "Vector2", as we want to constantly get our X and Y axis. In its binding, select "Mouse > Delta". Delta is apparently the change in pixels in Vector2 since the  last rendered frame mouse position. For our "Zoom", we'll add another action  named "Zoom" and set it to "Value" as well. We simply want a float here to know  whether we are scrolling up or down. The Value Type for float is called "Axis". Now, we'll use the value this input returns  to know how much we should scroll up or down but it currently comes with high values such  as "120" so we'll clamp it to a lower value. To do that, add a "Processor" of type "Clamp"  and set it to be from "-0.1" to "0.1". This Input also comes inverted, which  means scrolling up would return positive and scrolling down would return negative. We want the opposite of that, so add yet another  "Processor" but this time of type "Invert". When that's done, set its  Binding to be "Mouse > Scroll Y". Then, save the asset. Back in our "PlayerCamera", in the Input Provider  Component, select the corresponding Inputs, so "Look" for the "XY" axis and  then "Zoom" for the "Z" axis. We're now using the new  Input System for our Camera. We're only a few settings away of having  our Camera behaving like Genshin's camera. The first thing we'll be  doing is set our FOV to "60". The next thing is setting both  the camera "Body" and "Aim". The "Body" sets the algorithm that the  Camera uses to "Follow" its target. The "Aim" sets the algorithm that the  Camera uses to "Look At" its target. If we take a look at Genshin Impact camera, we  can see that we can rotate around the target. In the "FreeLook" Camera this is  known as an "orbital transposer". However, in the "Virtual"  Camera, the "orbital transposer" does not contain a vertical  rotation, but only horizontal. Thankfully, we can imitate  the "FreeLook" Camera setting using the "Framing Transposer"  Body together with the "POV" Aim. The "Framing Transposer" tries  to keep the camera centered to the Follow Object at the provided distance. The "POV" aim moves the camera according  to your input, which should translate to "where you are looking at", relative to the "Look At" target. If we enter Play Mode, our Camera should have the same orbital  behaviour that Genshin Impact camera offers. However, there are a few problems: Besides the camera movement being too fast, the faster you move your mouse  around, the slower the movement gets. What we want here is for the camera sensitivity  to be as close to the mouse speed as possible. To fix that problem, open up the "Aim" area and swap both inputs from "Max  Speed" to "Input Value Gain". Make sure your Vertical Axis also  has the "Inverted" option enabled, as otherwise we'll be rotating towards  the opposite vertical direction. Next, we'll set the speed on the vertical axis to  be "0.1" and on the horizontal axis to be "0.16", as Genshin Camera has a  faster horizontal movement. If we now move our Camera around, it should be slower and also have a  closer 1 to 1 sensitivity with our mouse. If you wanted a fully 1 to 1 sensitivity,  then you would need to set the speed to "1". There still are some problems left to resolve. One example is our vertical axis, as we  aren't able to rotate 90 degrees up or down. That's solvable by updating the "Value  Range" field from the vertical axis. We'll set it to be from "-90" to "90". For our Horizontal Axis,  we'll go with "0" to "360". I'm not entirely sure if we actually need this one but I'll leave it as is to  make sure nothing breaks. I'll also enable "Wrap" to allow the camera to keep rotating once we get  to the "360" degree rotation, as otherwise it would stop there and  we would need to move the camera back. The next thing is that if you start  moving your camera around and stop it, you might notice something: The acceleration and deceleration  of the camera are instantaneous. In Genshin Impact however there is a  small acceleration and deceleration. We can easily set that up by updating  the Vertical and Horizontal Axis "Accel Time" and "Decel Time" fields. For the vertical axis we'll go with "0.8"  acceleration and "0.05" deceleration time. For the horizontal axis, we'll also go with  "0.8" acceleration but "0.25" deceleration time. Our camera should now start or stop a bit slower. I'm not really sure what the  "Recenter Target" does here but I have mine set to "Follow Target Forward"  and it works fine so I'll add it here as well. In this case, it seems to be the same as the  "Look" one because both have the same target, but I don't really know what this "Axis  angles are relative to Target" means. I'm assuming it has something to do with  the "Vertical" and "Horizontal Recentering" and that it recenters relative to that  target, but I'm not completely sure. If you do know, please leave a comment below explaining it so that we  know what it actually does. This "Horizontal Recentering" option is  what Free Look Cameras don't provide us with but we'll only need this quite a bit  later so leave it disabled for now. For our "Body", we'll be setting  both the "X Damping" to be "0.2" and the "Y Damping" to be around "0.4". Damping is how fast or slow the camera tries  to keep itself centered with the target, which in this case, should be the "Follow" target. While we won't be needing to set this here, I'll also go ahead and set  the "Camera Distance" to "6". We now have a Camera working quite nicely but  we still need 2 more things to take care off. The first one is that currently our Camera goes  through the ground instead of colliding with it. The second one is that we  can't yet zoom in or zoom out. Thankfully, both are quite easy to do. Lets start by exiting Play Mode. For the Camera Collisions, go to the  bottom of the Cinemachine Component and open up the "Add Extension" dropdown. There should be an option  named "CinemachineCollider". Feel free to press on it. This should add a new component to our Camera Object that allows us to set  Collisions with the Camera. What we want here is to set the "Collide  Against" layer to something to collide with. To do that, we'll create a layer for our  Environment so that the Camera collides with every existing Environment instead of just the Ground. So, add in a new layer named "Environment". Then, go to all of our Environment  Game Objects besides the "Water" and set their layer as "Environment". When that's done, go back to the Camera and  now set the "Collide Against" to "Environment" and remove the "Default" layer from there. For the "Ignore Tag" we'll set it to "Player". Of course, we need to add this tag to  the player so select its Game Object and add the "Player" tag. Next, back into our Camera, we'll be changing  the "Strategy" of the Camera Collider. This is simply how the camera behaves  when colliding with something. In our case, we want the camera to "Pull  forward" when we collide with the Environment, which simply pulls the camera  to the front of the collider. I'll leave the rest with its default values  but feel free to change them if you want to. If we enter Play Mode, our Camera  Collisions should be working. That means that all that's  left is our Camera Zoom. Unfortunately, I don't think there's  a built-in functionality for this so we'll have to do it ourselves. Thankfully, with the Input Provider "Z"  axis and the Body "Camera Distance", this is quite simple to achieve. That's because the input provider "Z" axis gives  us the value of when we scroll our mouse wheel, while the "Camera Distance" is  how far we are from the target. So, go back to the "Scripts" folder  and create a new folder named "Camera". Inside, we'll create a new C# Script,  to which I'll name "CameraZoom". When you're done creating it, add it  as a component of our Player Camera. Then, open it up and remove the default methods. We'll start by creating 3 variables: The default distance that the camera will start at and the minimum and maximum  distances that the Camera can go to. So, type in "[SerializeField]  private float defaultDistance;" and default it to "6f". Then, duplicate the variable line twice and swap "default" with "minimum" and then "default" with "maximum". I'll set their default values  to "1f" and "6f" respectively. We'll also make it so we can update  these variables with a slider, so to do that simply add in after the  "SerializeField" attribute: "[Range(0f, 10f)]", meaning we can choose a value  from 0 to 10 through a slider. Next, we'll add two more variables:  A value to smooth our distance lerp and a value to multiply our "Z" axis value with. So, duplicate one of the variables above twice and  then change the first one to be named "smoothing" and the second one to be "zoomSensitivity". I'll default the "smoothing" to "4f"  and the "zoomSensitivity" to "1f". That's all the data we need to be able to set  in the inspector so now we need two more things: A reference to the Cinemachine Framing  Transposer, which represents our "Body" and a reference to the Cinemachine Input  Provider, which contains our "Z" axis value. So, create a new "private" variable  of type "CinemachineFramingTransposer" named "framingTransposer". Make sure you import the "Cinemachine" namespace. Then, create another "private" variable of type  "CinemachineInputProvider" named "inputProvider". To get their references, we'll  use the "GetComponent" method so type in "Awake" and inside type in "framingTransposer = GetComponent<CinemachineVirtualCamera>()", which gets our Virtual Camera. We'll now get our framing transposer by using the  ".GetCinemachineComponent<>()" method instead. For the type, we'll of course pass  in "CinemachineFramingTransposer". We use the "GetCinemachineComponent" method here because the "Body" is part  of the Cinemachine Component. For our provider, type in "inputProvider =  GetComponent<CinemachineInputProvider>();". When that's done, call in the  MonoBehaviour "Update" method and call in a new method named "Zoom();". We can now start zooming our camera. The way we'll do that is by  retrieving the value of our scroll, which we can do from the input provider "Z" axis. To do that, type in "float zoomValue  = inputProvider.GetAxisValue();". Here, we need to pass in an axis index,  which is the index of "2" for the "Z" axis. Then, we multiply this value by our "zoomSensitivity". We now need to add this value  to our current distance target, which we currently have no variable of. So, above, create a new "private  float" named "currentTargetDistance". This will start with a default value of "0" but  we want it to start with the "defaultDistance" so in the "Awake" method type in  "currentTargetDistance = defaultDistance;". Then, back in our "Zoom" method, type in "currentTargetDistance =  currentTargetDistance + zoomValue;". We need to make sure we clamp this target  distance to not pass our maximumDistance, so add in "Mathf.Clamp()"  surrounding our assignment and then pass in "minimumDistance"  as the second parameter and "maximumDistance" as the third one. We can now lerp the current  distance towards the target distance so that we slowly get there  instead of it being an instant change. To do that, create a "float" named "currentDistance" and assign to it  "framingTransposer.m_CameraDistance;". Then, type in "if (currentDistance ==  currentTargetDistance)", we "return;". This makes it so that if we're already at  the target distance, we won't do anything. To lerp our value, type in "float lerpedZoomValue = Mathf.Lerp(currentDistance, currentTargetDistance,  smoothing * Time.deltaTime);". We pass in "smoothing * Time.deltaTime"  here because we don't really want it to be an amount of seconds for the whole lerp but just keep it as consistent as possible at every  change and get there whenever it gets there. Then, finish it up by setting the "framingTransposer.m_CameraDistance = lerpedZoomValue;". That's all we need to Zoom our camera,  so save it up and go back to Unity. If we now enter play mode, we  should be able to zoom our Camera.
Info
Channel: Indie Wafflus
Views: 7,294
Rating: undefined out of 5
Keywords: genshin impact movement in unity, genshin impact movement, genshin impact in unity, genshin impact unity tutorial, unity cinemachine, genshin in unity, genshin movement in unity, genshin gliding in unity, unity 3d movement, unity gliding, unity physics based movement, unity rigidbody movement, unity swimming, unity genshin movement tutorial, unity 3d movement tutorial, unity third person movement, unity genshin impact, unity virtual camera, genshin camera unity
Id: bdMAfZBoG4U
Channel Id: undefined
Length: 20min 12sec (1212 seconds)
Published: Mon Feb 28 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.