#uVS First Person Camera & Player Controller Basics

1 messages · Page 1 of 1 (latest)

verbal lotus
#

Here's a tutorial to make a camera follow the player, basic player controller (move and jump) , look around with mouse.

What you will learn here:

• move player with new input system
• look around with mouse movement
• jump mechanics

verbal lotus
#

==================

#

PLAYER MOVEMENT

Step 1, add 2 new gameObjects. Plane and Capsule.

Plane for the floor, so player doesn't fall to the infinite and be able to demonstrate jump and moving around.
And Capsule as a placeholder for our player. This won't be seen in game. It will have the script machine in it (visual scripting graphs).

To make the camera follow the player, just drag camera inside your player. so it's "Child".

#

Step 2, click Capsule and add component "Script Machine" - this is where you'll add the graph logic to control the player. I prefer to save all script graphs in the same folder, and organize by sub folders to what they relate to.

For example, Inventory, UI, Player, Enemy, Weapons, etc. Organization is crucial.

Once done, should look like this your component. with the graph's name.

#

step 3, add Player Input component to your player. so it recognize inputs such as pressing keys or buttons.

and then open the graph where we will add the nodes to the script graph.

In case script graph editor window doesn't open, go to window > visual scripting > browse graph and open the graph you created and it should fix itself.

#

step 4, we add our first nodes. Where all the action starts with "Event" type of nodes.

Right click the graph to open the Fuzzy Finder, and click Events > Input to select "On Input System"

Both Button and Vector2. In the screenshot I explain why both.

Basically, Button are a "activation" detection only for action logic. While Vector2 gives you Axis (x, y) data used for movement logic.

#

Step 5, Add 2 object variables. mainCamera (type camera) and moveSpeed (type float)

Drag your main camera to your mainCamera variable slot to cache your camera and refer to it anytime. For this tutorial, Object variable is enough.

Assign a value (i.e. 5) to your moveSpeed variable. This defines the movement speed for your player.

Now, make sure you go to Unity > Preferences > Visual Scripting... and deselect "Human Naming". This helps to see node names similar to C#, so when you go to search for other tutorials... c# won't be that different to read.

And then start adding the nodes as shown in the graph below.
Right click the graph, and type search these names:

• right | Transform.right
• forward | Trasform.forward
• x get | Vector3.x
• y get | Vector3.y
• delta time | Time.deltaTime
• pos get | Transform.position (get)
• pos set | Transform.position (set)
• multiply
• add

note: left is what you type to search, right is what you select from results.

You dont need to type the entire node name, just part of it is usually enough

#

If you follow this tutorial up to this spot, this is what you should have. Capsule moves as expected. And you can see the graph flow in play mode. So now, you can check how it works in real time.

..And we need 3 more things to finish this tutorial.

• Camera positioned at player's "face" so you dont see capsule.
• Jump
• Rotate camera on mouse movement.

#

Step 6, Camera positioned at player's "face" so you dont see capsule.

In your Camera gameobject (Select it) change these values Z to 0, so camera is not behind. And Y to 0.8 so it's in the "head".

Unless you want a "Third Person" type where you see your player running and doing stuff.

Since it's "First Person" we set camera "In the head.

#

=====
JUMP

Step 7, To make your character Jump - you need the "addForce" node in mode Impulse. and use your variable in the Y value. So it shoots up quickly, and then stops to start falling.

To make this happen, first add a new component to your gameObject Player (capsule in this case) the "Rigidbody" component.

Make sure you constraint freeze rotation X, Y, Z... so it doesn't fall when applying movements/physics to this object.

Nodes you'll need:

• add force | Rigidbody.force (force, mode)
• new v | new Vector3 (x, y, z)

#

Step 8, Allowing jump ONLY when touching the ground. Or else, you could jump eternally... I assume that's not intended.

Add a new variable type bool "isGrounded". And add that to the jump graph using a IF. so it jumps ONLY if this variable is true.

Now we need to verify if there's a ground below.

  1. Add a new object layer. Select Plane (or any "floor" object) and select the layer that represents Ground.
  2. onUpdate node will verify on every frame, if there's a ground below. using "Physics Raycast".
  3. We input these values: Where the ray begins, where it goes and what should it detect.

So follow this graph using these nodes:

• on update
• pos get
• down | vector3.down
• layer mask | LayerMask Literal
• ph ray | Physics.Raycast (origin, maxDistance, layerMask, queryTriggerInteraction)
• if
• bool

And connect these as shown in the graph. Most of them are straight forward how to use. What this IF does.. when ray doesn't detect ground below, you set that variable bool false. so you cant jump anymore.

#

**Remember to add "Grounded" layer to your floor to make this work. **

#

If you've followed this tutorial up to this point, you should be able to replicate this behavior.

Now the player jumps ONLY when it touches the ground.

#

========================
LOOK AROUND W/ MOUSE

Step 9, Rotate camera on mouse movement.

To make this happen, we need a new input that gives up data of where the mouse is moving.

We take X and Y values from this input, and use it differently.

X mouse value rotates player object in Y angle. So it rotates left and right. to "see what's on your left/right" or even go back by turning around.

Y mouse value rotates CAMERA instead. So camera rotates up or down, to look up/down.

And it has a -1 multiply node, because we need to invert mouse input. So mouse up is camera look up.

And we clamp this value, to limit how far you can look up. otherwise, the camera will rotate indefinitely backwards and starts spinning...

Nodes you'll need for this:

• mult | multiply (scalar) ---> this allows you to set a -1 value in second input - inside the node.
• rotate | Transform.Rotate (euler, relativeTo)
• clamp | mathfClamp (value, min, max) ---> use the one with "FLOAT" output. Should be the first.
• eul set | Transform.localEulerAngles (set)

#

=============================

And that's it!

That's everything you need to go codeless way and build your first person videogame. If you followed this tutorial, you should have your player setup like shown in this video.

#

Here's the graph file you can just upload to your project and check these nodes. You'll still need to configure your player object (capsule) and the camera inside as a child, with Z 0 and Y 0.8.

And lastly, a big screenshot of the 3 parts of the script needed for this. Showing the variables used, as well.

Enjoy. If you have any questions, send a message in this thread below. Thanks for following.

verbal lotus
#

==========
Questions?

@unreal stump Responding to your question here

#

on Step 7. Do I add a separate island of nodes to my already existing graph Where I have the whole movement system from the previous step?

If you go until the end of this tutorial, you can see a whole picture of the three logics together, separated "island of nodes" (i like how that sounds). There's 3 of these groups: Movement, lookAround, Jump.

You can use ctrl + click to create a "window" and group nodes together, and then dragging the window from it's top moves all nodes inside. Pretty useful to re-organize

verbal lotus
#

@swift robin check these out

verbal lotus
#

Bump for newcomers

#

@strong siren take a look at this tutorial

sturdy pilot
#

Bump

earnest zodiac
#

@cursive isle Yep, **Update **for storing controls for that frame, then **FixedUpdate **to apply the controls to actual movement

#

in general, dont put physics in Update (some Unity physics things only run in FixedUpdate as performance-saving, you want to be in sync with that), and don't put control checks in FixedUpdate (because this ticks less frequently so you might miss the frame where you actually pressed a button)

#

so you will usually store variables from your controls in Update for use in FixedUpdate, like h for horizontal input, v for vertical input. isJumpRequest for if you press spacebar during Update (to be set back to false at the end of each FixedUpdate)

verbal lotus
#

Youtube Video Tutorial

How To Make A Player Controller With Unity 6, Physics & Visual Scripting With New Input System 2025

https://youtu.be/cBcAKS1OW0k?si=b0VZ_YTJX-4fADDV

==========
movePlayer?

  1. add rigidbody (constrain XYZ rotation so it doesn't fall)
  2. add player input (so keyboard is detected)
  3. add script machine and create new (use easy-to-read name)
  4. add moveSpeed variable float (to set speed)
  5. add node "on input system event vector 2" node, set [ Move ] as input action
    • find this her...
▶ Play video
cursive isle
cursive isle
#

i tried having gemini help but it started spazzing and thinking things that were plugged in wasnt plugged in

verbal lotus
#

Im not sure what have you done outside uVS - i mean, the gameObject settings.

Maybe share more images to compare data related to scripts. Sometimes its not the script (considering you followed the steps)

#

1 detail is enough to screw the rest. Thats the benefit of game logic 🤷🏻🤪

cursive isle
tardy rain
cursive isle
#

oh string variables, well it was orange in the tutorial so i assumed it was string cause string was orange

tardy rain
#

switch them to float and see

cursive isle
#

when i move the camera to a 3rd person perspective it looks like its orbiting the player while still staring forward

cursive isle
rain bane
#

you are setting the euler angles of the camera in world space, thats why its always facing foward

#

you should use the "set local euler angles" node

#

youre basically rotating the body, and then telling the camera to look foward in world space regardless of the body's rotation

cursive isle
rain bane
#

yes

#

i dont know why my nodes dont have the same names as yours
mine have "get" and "set" before the name of the node not after
maybe its a differnent unity version thing or something like that

cursive isle
#

so the camera now moves left and right but not up and down, also the direction i look does not match the direction i move

rain bane
#

im not really sure
look at the values in your script while its running
when you move your mouse left/right or up/down, do values change or are they stuck at 0 ? it looks like the vertical is stuck at 0 in your video but i cant really tell

#

move your mouse a lot cuz it could be small numbers that are hard to see any change in

cursive isle
#

are the movement and camera supposed to be connected? because to me it seems like the movement is the only thing tied to the player, meanwhile the camera is the only thing rotating instead of the player which would explain the problem with not moving where the camera is looking

rain bane
#

the force you're adding is in world space too, you can use addrelativeforce instead of addforce

#

that should make the movement follow rotation of the body

#

as for looking up and down not working i have no idea

cursive isle
#

okay that works now awesome, kinda stuck with doom 1993 vision for now though which can be figured out (maybe)

rain bane
#

i assumed that was disconnected for some other reason but that would be why its not working lol

cursive isle
#

nice catch but for some reason its the same effect, im noticing that theres only stuff for camera angle y but x is up and down right?

rain bane
#

uhh i dont know
you rotate the body left and right along the Y axis with the rotate node, and then you rotate the camera up and down along its x axis with the setlocaleulerangles, so it should be working..?

#

oh!

cursive isle
#

maybe i misunderstood something and wired something wrong? this is how its looking currently

rain bane
#

your mouse sensitivity is 0

#

so its multiplying by zero and never moving

cursive isle
#

oh thats weird

#

bruh... found it

rain bane
#

btw if you change a graph or object variable while in play mode, itll reset once you exit play mode, only the graph itself stays the same after exiting

#

thats probably why

cursive isle
#

cant believe the whole time the sensitivity wasnt set

rain bane
#

its easy to miss things i do it all the time lol

cursive isle
#

you also wouldnt happen to know how to add sprint would you?

rain bane
#

when you press a key (for example shift key) set a "sprint" bool to true, and to false if you release the key, and depending on that bool, you select a speed

#

the stuff happens and the vector under is is just placeholder for the rest of your script

#

you jsut multiply the force vector by that selected value

#

somewhere like here along that line in your script, thats where the multiply goes

#

or if you have a base speed variable, you can change that value when pressing the sprint key, something liek that works too

cursive isle
#

it looks like theres a vector 2 input system event option for sprint

#

not quite sure how to plug it in though

rain bane
#

i dont know what values come out of that vector so i cant really say

cursive isle
#

its the same event system that controls the movement just an option for sprint

rain bane
#

i dont know, it depends on the inputsystem asset thingy

#

maybe try and log the results and see what comes out

cursive isle
rain bane
#

looks like its just a button so i doubt it would give a vector out, it would just be (0 ; 0)

#

use the button variant of the node, not the vector2 one

cursive isle
#

on button click?

rain bane
#

yeah

#

this one i mean

cursive isle
#

found it, so how would i plug that into the main movement script?

rain bane
# rain bane

you set a sprint variable to true or false depending on weather or not the button is pressed or released (on the left of the image)
and with that sprint bool you select a speed multiplier, and multiply your vector by that before the addforce

cursive isle
#

so the sprint variable is a bool or a float?

rain bane
#

both can work
you can make it a bool to select between two floats, or you can make it a float and use it to multiply directly

#

it does look simpler this way

cursive isle
#

so for my case would i be attaching that sprint multiplier to the multiplied force?

rain bane
#

yeah

cursive isle
#

i notice you have two checks to see if youre sprinting, are two necessary?

rain bane
#

one is set to onPressed and the other is OnReleased

#

so one of them sets it as true (or 2) and the other one sets it as false (or 1)

cursive isle
#

does onHold not respond as well?

rain bane
#

you could use onhold but when would it be turned off then ? it would be set to true every frame you hold it but when you let go it would stay true, so its not really useful

cursive isle
#

aahh okay

#

like this?

rain bane
#

yeah that works

cursive isle
#

apparently not, error says cannot convert from UnityEngine.Vector3 to UnityEngine.Rigidbody

rain bane
#

plugged into the wrong spot

#

you can look at your graph when you get errors, the nodes should usually light up red to tell you where the error is

#

like this

cursive isle
#

ah okay got it, works now

#

dude thanks a bunch you've been a huge help

rain bane
#

you're gonna have to get used to doing all that kinda tinkering and stuff, its hard at first but you wont get far if you cant figure out how to make stuff work on your own xd

rain bane
cursive isle
#

actually one last thing, when i start the project it automatically assumes that the sprint is pressed and i have to press it again to reset

rain bane
#

what is the default value of your sprint variable ?

#

it should be the same as your "sprint key released" value

cursive isle
#

oh yeah that was it, i had it set to 2 originally expecting it was a boost at first

#

alright i think thats actually it now, thanks for your help

verbal lotus
#

Amazing team work ❤️ good job @cursive isle making this work as you wanted is a massive win.

Player controller is like the most important game feature. Its what makes the game playable lol you know, controlling the player

earnest zodiac
#

nice custom node, i have found myself needing a node that does stuff from time to time