#uVS First Person Camera & Player Controller Basics
1 messages · Page 1 of 1 (latest)
==================
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.
- Add a new object layer. Select Plane (or any "floor" object) and select the layer that represents Ground.
- onUpdate node will verify on every frame, if there's a ground below. using "Physics Raycast".
- 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.
==========
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
@swift robin check these out
Bump
@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)
Youtube Video Tutorial
How To Make A Player Controller With Unity 6, Physics & Visual Scripting With New Input System 2025
==========
movePlayer?
- add rigidbody (constrain XYZ rotation so it doesn't fall)
- add player input (so keyboard is detected)
- add script machine and create new (use easy-to-read name)
- add moveSpeed variable float (to set speed)
- add node "on input system event vector 2" node, set [ Move ] as input action
• find this her...
im not particulaly sure what im doing wrong, the camera moves side to side but not up and down, on top of that the movement and camera are completely disconnected like the camera and player are separate
i tried having gemini help but it started spazzing and thinking things that were plugged in wasnt plugged in
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 🤷🏻🤪
what should i take pictures of? i havent messed with anything but this from what i can remember
Why are you using string for you mouseSensitive and cameraAngleY variables?
oh string variables, well it was orange in the tutorial so i assumed it was string cause string was orange
switch them to float and see
so interesting thing, it finally works and they spin the player now but the camera just keeps keeps staring ahead for some reason
when i move the camera to a 3rd person perspective it looks like its orbiting the player while still staring forward
this is what i mean
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
so i replace transform set euler angles?
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
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
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
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
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
okay that works now awesome, kinda stuck with doom 1993 vision for now though which can be figured out (maybe)
wait didnt you just forget to connect the flow to the localeulerangles(set) node-?
i assumed that was disconnected for some other reason but that would be why its not working lol
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?
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!
maybe i misunderstood something and wired something wrong? this is how its looking currently
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
cant believe the whole time the sensitivity wasnt set
its easy to miss things i do it all the time lol
you also wouldnt happen to know how to add sprint would you?
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
it looks like theres a vector 2 input system event option for sprint
not quite sure how to plug it in though
i dont know what values come out of that vector so i cant really say
i dont know, it depends on the inputsystem asset thingy
that
maybe try and log the results and see what comes out
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
on button click?
found it, so how would i plug that into the main movement script?
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
so the sprint variable is a bool or a float?
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
so for my case would i be attaching that sprint multiplier to the multiplied force?
yeah
i notice you have two checks to see if youre sprinting, are two necessary?
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)
does onHold not respond as well?
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
yeah that works
apparently not, error says cannot convert from UnityEngine.Vector3 to UnityEngine.Rigidbody
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
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
aw no problem ^^
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
what is the default value of your sprint variable ?
it should be the same as your "sprint key released" value
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
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
nice custom node, i have found myself needing a node that does stuff from time to time