I’m very new to blueprints so please feel free to share if you know a better way to achieve the same result and please do post videos of anything you make with this method. Would be great to see what people come up with.
This example uses Blueprint sidescroller project as a start point and will modify it to the point your character is locked to a spline so that all you are pressing is left and right on the left analogue stick as you can see in the video below (whilst it might look quite crude, the idea is a start point for people to develop from)
Create a new Actor Blueprint (in this example named Spline)
In the Components view of this BP, create a spline (shape, not spline mesh).
Open the MyCharacter blueprint and go to the Graph view.
Create a Variable in the left panel and call it Spline_blueprint or an appropriate name.
Open the Variable Type dropdown list below and type _C into the search box. This will list all of your blueprints that you can reference. Select Spline_C from the Object section.
Click the eye icon next to your new variable and it will turn yellow.
Finally you MUST write something in the Tooltip entry box in order to choose what blueprint will be referenced when you reach the next steps. e.g. ‘Referenced BP’.
You will see the eye icon has turned green if you have done this correctly.
- Delete Player Start in level and drag an instance of the Mycharacter BP into level.
- In Details panel set Auto Possess to Player 0 (this is now your player start)
- Also drag an instance of your Spline blueprint into the level and place some spline points (click on end point and Alt + Left click drag new points out)
- Return to the MyCharacter blueprint you placed and look in the details panel for ‘Spline Blueprint’. This is the exposed variable you previously made. Click on the dropdown box and choose your Spline blueprint from the list.
In character BP graph create the following setup:
This says that when Play Begins, the variable ‘Distance Along Spline’ is set to 0. After this the Capsule Component (i.e. the character Root) is moved to whatever location is set within that variable (you will need to promote Distance entry in the “Get World Location at Distance Along Spline” node to a variable named ‘Distance Along Spline’) and that the spline being referenced is Spline 1 in the blueprint called Spline.
SAVE YOUR BLUEPRINTS!
You can see this working if the start point of your spline in the level is set away from the position of the MyCharacter blueprint.
Dropping into game, you will see that the character spawns at the start of the spline, rather than the location of the MyCharacter blueprint in the level.
Now that we have set our first location, we want to set a new location each frame. This location will be defined by the ‘Distance Along Spline’ variable we currently have. Up to now it has just been set to 0, but you can change this value however you like.
In my example I will use the ‘InputAxis MoveRight’ event which is already setup in the project to modify the variable based on how much I push the left stick on a 360 controller.
As the variable will be changing, we want to update the location every frame.
Create the following additions to the MyCharacter Graph:
In this setup, whenever a MoveRight event fires (by pushing the left stick or using the assigned keyboard shortcuts) the axis value (which can be positive or negative) is added to the current value stored in the ‘Distance Along Spline’ variable. The resulting value is stored in the variable and a new location is set per Tick (even if this location hasn’t changed).
Whilst you can move back and forth along the spline, you will notice that your height doesn’t change as the world location is being set in all 3 axes (X,Y and Z). The movement is also incredibly slow and doesn’t match the leg movement of the character so you might want to add in a multiply node (Float*Float) before the ‘Add’ node to increase the Axis Value.
At this point I’m learning as I write this so I might not have the most graceful solution. I’ve never used a Trace but it seems like the right thing to do… so… fingers crossed!
If we promote the return value of the ‘Get World Location at Distance Along Spline’ to a new variable called ‘Current Location’, we can store this location every Tick and fire a Trace from this location at the same time.
This example will fire the trace from the current location to the same location in X and Y, down to a world height of 0
With the Draw Debug Type set to Persistent, we can drop into game and see that the line trace is indeed firing down from the player and hitting anything at 0 height in Z and above (you might need to add more types into the Make Array node based on your level contents or change the Z height to a negative value).
If we now break the Out Hit of the Line Trace to a Hit Result, we can create a new variable from the Impact Point and called ‘Trace Hit Location’ and set THIS as the new World Location of the Capsule.
If you hit Play at this point you will see that the player sits on the ground, but his waist is intersecting the ground. If you add in a Vector+Vector node you can offset the Trace Hit Location (I’ve used 100 to lift the character 1m upwards of the Trace Impact Point). Further to this I have also added the new variable ‘Jump Height’ into the equation. When InputAction Jump is pressed, an offset of 200 units (2m) will occur in Z. When it is released, this value will be 0 in Z.
Play now and you will see the snap to jump height whilst you hold the jump button, otherwise you should be at ground height.
This started out as a brief tutorial for a forum member who was struggling with spline locking a player/camera but has turned into something bigger so rather than refining the jump I will simply add the correct character rotation and leave it here…
There are a few steps:
- Go to the InputAxis MoveRight event and promote the Axis Value to a new variable
Now we can set World Rotation of the Capsule Component at the current Distance Along the Spline, just as we initially set the World Location.
If you hit play you will see that the rotation is only correct whilst running from left to right, but he runs backwards (moonwalks) when going the other direction along the spline. This is the reason we made the Axis Value variable in the previous steps.
With the following setup I have stored the Current Rotation as a variable and then added a Branch to the exec. If the MoveRight Axis Value is equal to, or greater than 0, then the stored current rotation will be set on the Capsule. If not (i.e. the Axis Value is negative) then 180 degrees in Z will be added to the Current rotation and applied to the capsule, resulting in him facing the correct way whilst running backwards along the spline.
Update your camera position and rotation from the same spline or even its own spline (or lock it to the player) and you’ll get a nice drift through the world which you’ll see when I get around to updating my own thread here - https://forums.unrealengine.com/showthread.php?3902-Seeking-guidance-for-movement-system-(spline-locked-side-on-free-quot-flight-quot-)
There’s lots to refine here such as the jump, the fact you snap up surfaces when you meet them, and plenty more, but I hope it’s helpful to people. It’s been good to learn new things as I wrote this up and I’ll be showing off my own implementation soon, but for now it’s bedtime.