Could I get some help making a 3D player movement system?
- Edited
trizZzle
Ok the tutorials really nice! I got the movement for the most part ready to go! One problem I'm facing is the camera, I want to make in first person so I've followed some tutorials and again I seem to be breaking it (or maybe they are out dated) right now I do have some code, it doesnt seem to work and for the life of me I dont know why (cause I dont know how it would work but here goes!)
func _unhandled_input(event):
if event is InputEventMouseButton : # lock camera and what not
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
elif event.is_action_pressed('ui_cancel') :
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and not GameValues.inMenu : # make sure we are in first person and not in a menu
if event is InputEventMouseMotion : # if the event is mouse motion, rotate!
neck.rotate_y(-event.relative.x * 0.01)
camera.rotate_x(-event.relative.y * 0.01)
camera.rotation.x = clamp(camera.rotation.x,deg_to_rad(-30),deg_to_rad(60))
now from doing some debugging I can say that whatever InputEventMouseMotion is never triggered, ever.
Although any code before it is indeed triggering so something goes wrong there, as to how to fix it I'm early in learning this stuff and so far have not been able to figure it out. So your help would be nice, thanks!
Thanks!
- Edited
don't use an elif
for the ui_cancel just a regular if.
func _unhandled_input(event):
if event is InputEventMouseButton : # lock camera and what not
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if event.is_action_pressed('ui_cancel') :
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
print("mouse is captured")
if not GameValues.inMenu : # make sure we are in first person and not in a menu
print("passed through inMenu related check")
if event is InputEventMouseMotion : # if the event is mouse motion, rotate!
neck.rotate_y(-event.relative.x * 0.01)
camera.rotate_x(-event.relative.y * 0.01)
camera.rotation.x = clamp(camera.rotation.x,deg_to_rad(-30),deg_to_rad(60))
I'd probably also not put the checks for MOUSE_MODE_CAPTURED and GameValues.inMenu both onto the same line. Right now you have a hard time telling which of those checks causes you problems.
edit: Actually thinking about it I can see why you wanted to use elif for the ui_cancel but in that case maybe its worth keeping track of menu state and use a match based on that, while also being able to use the same state variable check also for rest of the relevant code...
Megalomaniak
Ok so I tried the code you suggested (PS: thanks for the pointers) but I have some problems, I realized that this only updates anytime I press a button and not the mouse actually moving, probably because its locked in the center of the screen and doesn't move, therefore the event is never mouse motion, so I was going to plug it into a process function but I realized that the when turning the camera:
Megalomaniak neck.rotate_y(-event.relative.x * 0.01)
camera.rotate_x(-event.relative.y * 0.01)
I use the event variable that was defined inside of func _unhandled_input(event): of course in a process function I cant get this (well to my knowledge) so what can I do instead? Cause I have no idea what I can use instead, probably because I for the most part dont even know what it does!
So yup
If you know how to fix it and would lend me your knowledge that would be great! If you need anything else about my project like info or something, I'm more than happy to provide.
Thanks again!
- Edited
Frodev I realized that this only updates anytime I press a button and not the mouse actually moving
The _unhandled_input(event): is just one of the loops for doing input stuff. You should maybe try the normal _input(event): loop too. Some things will work better in one than the other.
Frodev I use the event variable that was defined inside of func _unhandled_input(event): of course in a process function I cant get this (well to my knowledge) so what can I do instead?
Pretty sure you can call on the Input and InputEvent classes from process loops, so you might be able to make that work for you. For an example, read the velocity property from the InputEventMouseMotion class.
Megalomaniak
Ok I got it working! Thanks so much!
Megalomaniak
Hi there quick question, I just realized that the direction you move in is not based on the camera direction.
I've tried a couple of things, I was gonna try vector3.Forward and just use the camera position until I realize that from my knowledge, it isnt possible (or well I cant figure it out it probably is possible but what would I know).
So here I am asking for help!
How I have it now the camera is rotated only on the X and Z access where as the Y is rotated in another node, this node being the parent of the camera but the child of the player:
Anyhow this is how I am currently moving the player:
func _physics_process(delta):
# movement -----------------------------------------------------------------
var direction = Vector3.ZERO
if Input.is_action_pressed('WalkRight') :
direction.x += 1
if Input.is_action_pressed('WalkLeft') :
direction.x -= 1
if Input.is_action_pressed('WalkBackwards') :
direction.z += 1
if Input.is_action_pressed('WalkForward') :
direction.z -= 1
if is_on_floor() and Input.is_action_just_pressed("Jump") :
targetVelocity.y = jumpImpulse
if direction != Vector3.ZERO :
direction = direction.normalized()
$Pivot.look_at(position + direction, Vector3.UP)
targetVelocity.x = (direction.x * speed) * GameValues.gameSpeed
targetVelocity.z = (direction.z * speed) * GameValues.gameSpeed
if not is_on_floor() :
targetVelocity.y = (targetVelocity.y - (fallAcceleration * delta)) * GameValues.gameSpeed
velocity = targetVelocity
move_and_slide()
As we can see I just add to either the X or the Z or whatever, but obviously that isnt going to work but I currently dont know a way to do otherwise, if you do know a way please tell me, I've already spent 30+ minutes researching this topic but nothing so far.
Thanks so much!
Do you understand the difference between local space and global space transforms?
Megalomaniak
A little bit yes, I believe I understand the basics of it.
Also, what node is the script attached to? You are likely mostly dealing with local space values of nodes here and should perhaps instead use global coordinate space values in certain cases instead. And be careful of mixing local and global space values unless you know you need to do so.
Megalomaniak
The script is attached to the node called player:
I see what you are saying about using global positions, I assumed that for some reason just use move_and_slide() would do that on the global side.
But out of curiosity why does moving it using global positions do anything really? Is this gonna make it go in the direction or the camera? Cause I feel like it wouldnt but I dont know if thats how that works so here I am!
- Edited
your camera orientation can be different from the nodes above it in hierarchy, so trying to apply it's local z axis transform to another might lead to unwanted results.
Methods such as LookAt might take local coords as inputs and do the conversions to global coord space for you automagically but it's something to look out for.
Ok I've tried goofing around with it for a little bit, so far I havent been able to figure anything out on how to solve the problem.
So I was wondering if you could like explain a way to actually do this, maybe some examples or something. I think I'm really struggling to grasp this concept
Sorry if this sounds like I want you to write scripts for me, I genially cannot figure it out
Frodev How about you paste your whole script in here? Or in a github gist or such if you prefer.
- Edited
Frodev You should first make a simple movement setup with a fully static camera that doesn't follow the player. This should give you some fundamental insights on how to work with 3D vectors and basic kinematic movement in 3D. You'll see that this part is very similar to 2D. After that, add a simple third person camera follow to the setup, without any camera rotation. And after you get this to work, add some camera rotation to that follow. And finally you can tune the whole system to look and feel good for the player, by adding smoothing, easing, transitions etc...
When coding, always try to divide a problem that looks overwhelming into simpler sub-problems, and tackle one by one, gradually building the system from a simple start towards more complexity. You can divide as much as needed until every part of the big problem looks trivial to solve. Then just add all those simple solutions together and voila - you solved the complex problem.
There's a reason why the whole thing is called game (or software) development - you gradually develop the thing In the process, you also develop your knowledge and problem solving abilities.
Otherwise you'll likely never understand what you're actually doing and will always depend on some premade code that you have no clue how it operates. In the long run, it'd be very hard and frustrating to complete a game working like this.
xyz That's a great idea. One step at a time.
okay firstly i personally think that you should reconsider your choice of starting Gamedev with making 3D games, 3D is much more complex than 2D, and i feel like there's more learning resources for 2D Godot games than there is for 3D games, If your issue is with having to make art assets then that's absolutely not a problem, most if not all free tutorials on Youtube will provide you with free to use 2D sprites and will teach you how to import them in the engine
also i feel like the reason for why none of the 12 tutorials worked for you is because they don't fit in with your current project ,(I mean no way 12 tutorial for the most basic thing are just completely broken ?) here's the thing : as a beginner in Godot you should follow a complete tutorial series rather than just separate small tutorials for separate features in your game, I mean don't search for "how to create basic player movement" but rather search for "simple 3D game tutorial", this way you won't have to worry about the code not working, since it's all built off of one series
anyway I'm sorry if this reply was unhelpful, i was in a similar place to you where i felt frustrated and couldn't get the most basic features to work, but this sort of advice really helped me learn the best learning method !
good luck on your game dev journey
buzzbuzz20xx
You do have some very good pointers actually!
But anyhow due to my situation I feel like its the best for me, as I've been making 3D games for over 3 years now and when I chose to come use godot I did indeed start out with 2D but me being not good at pixel art, or 2D animations for that (which took me 3 days to complete a pretty ok thing, only to realize it looks off and have to go redraw everything :<)
And I personally am trying to make like my own game so I dont as much want to keep using others sprites.
And in the end 3D modeling is like one of my favorite things to do so I wanted to learn to make 3D games so I wouldnt have to keep suffering
buzzbuzz20xx also i feel like the reason for why none of the 12 tutorials worked for you is because they don't fit in with your current project ,(I mean no way 12 tutorial for the most basic thing are just completely broken ?) here's the thing : as a beginner in Godot you should follow a complete tutorial series rather than just separate small tutorials for separate features in your game, I mean don't search for "how to create basic player movement" but rather search for "simple 3D game tutorial", this way you won't have to worry about the code not working, since it's all built off of one series
This is actually a really good point dont know why I didnt think of this.
Overall thanks for all the advice and I wish you luck on your dev journey as well.