Bézier movement
Now that we have our bézier curve and our player set up, it is time to start making the player move across the curve.
Reading the input system
First, we need to create a script that will control the player's movement and positioning on the curve. We then attach this script to the player object. Remove the "void Update" since we don't need to use it. Your script should look now something like this.
Let's add a private Vector2 to store our direction input we get from our input system.
Now lets make a function that we will later use inside our Player Input component to read out our vector2 direction input.
Now in order for us to actually use the input system in our script, we need to add it at the top of the script by typing in "using UnityEngine.InputSystem;".
Now we can add the following line between the round brackets of our new function we just created, "InputAction.CallbackContext *NAME*". I normally put context on the part where a name should be, but you can change it to whatever you feel comfortable with using.
Now in order to store the context in our vector2 variable write the following line:
"directionInput = context.ReadValue();".
Now that we have this set up we can go back into Unity to our Player Input component we added.
To connect the script with the Player Input we need to open up the "Events" drop-down list first.
Now you'll see a lot of options but what we are focusing on is the name of our action map. We need to open our action map to see our actions we set up previously.
We now see our own created actions displayed.
For now we want to read out our movement so we hit the "+" and see the following.
We then drag our player object to the empty object slot and we see that "No Function" isn't grayed out anymore. This means we can select a function we want to connect to the movement.
In order to set it to the script we open the drop down list, go down to our script and select our function that is located at the top of our list.

And with that we have now successfully connected the function inside our script with the player input system.
If you want to know how to test if it's actually working properly, follow the steps below. If not, then click on position player on curve to skip this section and continue on with the rest of the tutorial.
In order to see if it's actually working we need to go back to our script and add an extra line to let us see our vector2 variable in the inspector. Right now the vector2 variable is private, meaning it won't show up in the inspector nor is it accessible to any other scripts we will make in the future.
So to make it visible in the inspector, without changing it to public, we add "[SerializeField]" either above or in front of it.
What this allows us to do in the future as well is set certain objects, scripts, etc. reference via the inspector to a script's variable without it being publicly accessible via any other method. This makes things more secure and can't be manipulated from outside an editor.
In Unity you should now see that your vector2 variable is now visible in the inspector.
Now press the play button and press your keys or controls you have set up for your movement. When you go up and down you'll see the Y value change between 1 and -1, the same goes for the X value. If this is correct you have successfully confirmed that you've set up the Player Input with your script correctly.
Position player on curve
Now that we have our input direction set up, it's time to position the player on the curve. To start off drag your player away from position 0,0,0 a bit. This is easier to see it working after the following bit of coding we're about to do.
Next, create an empty game object and reset its position to 0,0,0. You can change this position later, but we'll get there eventually once other things are set up. Again, I like to name my game objects to what they represent, but you can name it however you feel like. Then attach the your path layout script to the object and it should look something like this.
Now what we can do is adjust points positions inside the scenic view to create a path layout. You can make yours as long, short, straight or curvy as you'd like.
Now that we have our path layout done, let's set up the reference in the player's script. To make it easier to follow along I will refer to the curve as a path from now on.
Now what we need a vector3 variable to store our current position based on progress along the path.
The last variable we need is a float variable to get our transform point of the path.
Now we can make our function that positions our player on the curve. To do this we need to get our point from our path layout script, provided with a float value. Then we set that value to our vector3 variable to store it. Lastly, we set our local position equal to our stored vector3 variable so our player actually gets positioned on the curve.
The last thing we need to do in our script is add this function into our "void Start".
We can now go back to Unity and see the following change appear in the inspector when click on our player object.
You can either drag your path game object into the empty slot or press the little circle with dot inside it and select the path game object that way.

Now if you press the play button and you'll see the player position itself at the beginning of the path.
With that in place you have successfully positioned the player on the curve. All we have to do now is make the player move across it.
Move player across the curve
To move the player across the curve we can do this in many different ways. For early testing I would suggest doing this in update, but I like to work with coroutines for these types of movements. If you want to use update you can do that too, but there are some small difference between doing it via update and a coroutine. For this tutorial I'll be using the coroutine method.
Let's create a new IE-numerator that we're going to use to move the player across the curve. A good thing to know is that you also have to do a "Yield return" inside the coroutine, otherwise you'll get an error saying that not all paths return a value. In our case we want to return or progress float variable so we add that behind our yield return.
At this point all this coroutine will return is zero, because we never increase the progress value. The way we can increase that is by making use of "Time.deltaTime". Time.deltaTime is the completion time in seconds since the last frame. So if we run the game at 60 FPS it means the game is currently updating 60 times per second.
So what we can do is increase our progress variable overtime by doing "progress += Time.DeltaTime;".
Now this will work, but if we test this out in Unity the player will instantly move to the end of the path instead of smoothly moving over there. To adjust this we have to divide the Time.DeltaTime with a new float variable so we can adjust the speed the player is moving along the path. We can keep this variable private but we serialize it so we can adjust the value of it via the inspector.
Going back to the coroutine all we have to do is add this variable behind the divider.
Now what we need to do before we return our progress is update our players position on the curve just like we did in our position player on path function.
The last thing we need to do in this coroutine is wrap all of in a while loop. A while loop will keep looping until it reaches it's parameter. In our case, we keep looping until our progress value is no longer smaller then one.
Now to test this out we can start this coroutine after we positioned the player on the curve. To do this we write, "StartCoroutine();" and between the round brackets we type the name of the function, including the round brackets behind the name.
We can now go back into Unity and adjust our speed value for what we want to have when we move on the path. For testing purposes I've set mine to five, but you can set it to whatever value you see fit. The end result will look like this.

As you can see the player moves along the path correctly, but we're not facing the direction of the path. Right now it looks like we're sidestepping along the path. To fix this we change our look direction towards the path.
What we do is we take our current position on the path and add on the "GetDirection" we get from the path once we provide our progress variable as a parameter into the function. So at the end our coroutine will look like this.
We can now go back into Unity, press play again and we'll see our player not only moving across the path, but also facing its direction.

Right now we get a variant number as our progress value because we only check if it's smaller than one. This is fine, but once we surpassed that check and we increase the value again, we potentially could exceed over the set threshold. So for that we build in an extra check to see if our variable does exceed over the set threshold value. If that happens we set it back to our set threshold value. In the function it will end up looking like this.
So we can move forwards on the path and prevent it from exceeding over the threshold. But what if we want to go backwards? For example, you progressed to the next level, but want to return to the previous level to maybe retry it for a better time or a higher score. Right now we can only go forward and have no way of going backwards.
To solve this we wrap our while loop around an if statement checking if our progress is smaller the one.
Now for going backwards we can basically copy the entire while loop, but don't paste it in yet. Underneath where the if statement ends we need to add an else statement. In here we can paste our while loop. It will end up looking like this.
Now what we have to do is reverse everything that is inside the else statement. What I mean by that is everything that is "<" should be ">" and vise-versa. Same goes for the "+". The last thing we need to change out is everything that has a one must be a zero. The end result will look like this.
With this setup your player can now walk forwards and backwards on the path while looking in the direction the player is moving.
You're now done with setting up the movement, but we can add in two extra lines of code to test out if the player is actually going back and forward. If you don't want to test it then this is the end for this part of the tutorial and you can continue on with the next step.
For those interested in how to test this, just add the "StartCoroutine(MovePlayer());" underneath both the while loops. That way you create an infinite loop so you can see your player going back and forth across the path.
The end result should look like this.

Last updated
