So at the moment I have a kinematic body and a platform to collide against. I have a scene for the KinematicBody itself to keep it seperate from the game, which has two extra gimbal spatial nodes, main gimbal for 3rd person left and right rotation and the inner gimbal for the up and down rotation. (i forget the cooardinates, im assuming its not the same as Blender) The camera is attached to the first gimbal node and its position is offset to the player. Basically a 2 axis gimbal system to replicate a 3rd person camera!! I learnt this by watching https://youtube.com/watch?v=ypCP2cKyh68 which helped me a lot.

extends Spatial

func _ready():
	set_process(true)

func _process(delta):
	
	var left_analog_axis = Vector2(Input.get_joy_axis(0,JOY_AXIS_2), Input.get_joy_axis(0, JOY_AXIS_3)) * 1
	rotate_y(-left_analog_axis.x * delta)
	get_node("innergimbal").rotate_x(-left_analog_axis.y * delta)

	if left_analog_axis.length() > 0.25:
		rotate_y(0 * delta)	
		get_node("innergimbal").rotate_x(0 * delta)

this code is utilizing an analog stick from a ps4 controller. It works well enough. I can rotate around the player along with the values from the axis meaning I can allow for pressure sensitivity. I've also applied similar code to the kinematic body itself which looks like this.

extends KinematicBody

func _ready():
	set_physics_process(true)

func _physics_process(delta):
	
	var left_analog_axis_move = Vector2(Input.get_joy_axis(0,JOY_AXIS_0), Input.get_joy_axis(0, JOY_AXIS_1))
 
	if left_analog_axis_move.length() > 0.25:
		move_and_slide(Vector3(left_analog_axis_move.x * 15, 0, left_analog_axis_move.y * 15))

I can move the player forward, backward, left and right along with the pressure sensitivity. The camera rotates around the player, but does not change the direction the player is facing. Is there any way around this? I assume that this is a common problem with 3rd person cameras. This could be due to a lack of understanding the concepts behind 3rd person camera techniques. Any suggestions or help would be much appreciated. I'm going to link to my current godot proj so feel free to take a look.

https://github.com/winnieTheWind/3rdPersonCameraWithAnalogStick

Thanks.

The reason your character isn't rotating with your camera is because you are not rotating the player (at least from the code snippets you've provided. I have not checked the Github project.)

If you want the character to turn with the camera, you need to also rotate the player by the same amount of rotation that you are applying to the camera. Something like this player.rotate_y(-left_analog_axis.x * delta) should make the player rotate with your camera.

I tried rotating the player as I move the right stick axis. It only rotates its body but doesnt change. I was thinking I could use a spatial, and the player, gimbal and inner gimbal are parented to the spatial. If I rotate the spatial, would the direction vector stay the same but it rotates on its spatial.~~~~ Just a hunch!

Basically I want to have capabilities of 3rd person view. Strafing on the left stick, Camera rotate on the right stick.~~~~

EDIT:

extends KinematicBody

var speed = 600
var velocity = Vector3()

func _ready():
	set_physics_process(true)


func _physics_process(delta):
	
	velocity = Vector3(0,0,0)
	
	var leftstickaxis = Vector2(Input.get_joy_axis(0,JOY_AXIS_0), Input.get_joy_axis(0, JOY_AXIS_1))
	var rightstickaxis = Vector2(Input.get_joy_axis(0,JOY_AXIS_2), Input.get_joy_axis(0, JOY_AXIS_3))
	
	#rotate kinematic body
	rotate_y(-rightstickaxis.x * delta)
	
	#push forward and back
	velocity.z = leftstickaxis.y

	#add speed
	velocity * speed
		
	move_and_slide(velocity, Vector3(0,1,0))

I stripped it back a bit so now the camera is parented to the kinematic body.

Are you trying to move the player relative to the camera?

If that is the case, then you need to get the camera's global transform and use its rotation basis to get the directional vectors for movement. Something like this should work:

var leftstickaxis = Vector2(Input.get_joy_axis(0,JOY_AXIS_0), Input.get_joy_axis(0, JOY_AXIS_1)) direction = Vector3(leftstickaxis.x,0,leftstickaxis.y) direction = direction * speed * delta if velocity.y > 0: gravity = -20 else: gravity = -30 if leftstickaxis.length() > 0.25: print("resting dead zone") velocity.y += gravity * delta """ Left/Right movement (relative to the camera's X axis) A positive value will move the player towards the X arrow on your camera. By contrast, a negative value will move the player away from the X arrow on your camera. To check your camera's local axis, select the camera and click the little box icon to switch to local object mode """ velocity *= direction.x * camera.global_transform.basis.x.normalized() "Same thing for Forward/Backward movement (using the Z axis instead of the X)" velocity *= direction.y * camera.global_transform.basis.z.normalized() velocity = move_and_slide(velocity, Vector3(0,1,0)) if is_on_floor() and Input.is_action_pressed("ui_accept"): velocity.y = jump

The above code should work, but I have not tested it. Let me know if it doesn't and I'll test the code and get a working code snippet :smile:

Combine this with rotating the player when you are rotating the camera, and the player should move around seamlessly with the camera.


I tried rotating the player as I move the right stick axis. It only rotates its body but doesn't change I'm not sure what you mean by it rotates its body but doesn't change. What is not changing?

Sorry I meant the body rotates but the direction doesnt change. Thanks for the help. I'm gonna check your adjustment against mine. I initially had the camera/kinematicbody rotating on the right stick, then I recoded it and accidentally assigned the left stick for rotation

So I'm a little shaky on how to access variables from a different node (like the camera) so bear with me and excuse my ignorance on using the right terminology :smile:


extends KinematicBody

onready var camera = get_node("Camera")

var speed = 600
var gravity = -8.3
var velocity = Vector3()
var direction = Vector3()


func _ready():
	set_physics_process(true)

func _physics_process(delta):

	var rightstickaxis = Vector2(Input.get_joy_axis(0,JOY_AXIS_0), Input.get_joy_axis(0, JOY_AXIS_1))
	
	direction = Vector3(rightstickaxis.x,0,rightstickaxis.y)
	direction = direction * speed * delta
	
	velocity.y += gravity * delta
	
    #Left/Right movement (relative to the camera's X axis)
    #A positive value will move the player towards the X arrow on your camera.
    #By contrast, a negative value will move the player away from the X arrow on your camera.
    #To check your camera's local axis, select the camera and click the little box icon 
	#to switch to local object mode

	
	velocity *= direction.x * camera.global_transform.basis.x.normalized()
	
    #"Same thing for Forward/Backward movement (using the Z axis instead of the X)"
	velocity *= direction.y * camera.global_transform.basis.z.normalized()
	
	if velocity.y > 0:
		gravity = -20
	else:
		gravity = -30
	  
	velocity = move_and_slide(velocity, Vector3(0,1,0))
	 
	if is_on_floor() and Input.is_action_pressed("ui_accept"):
		velocity.y = 5

At the moment nothing moves, if I plug direction into move_and_slide instead of velocity I get the controller working but not functioning how it should. Also, I changed the camera to be attached to the kinematic player. I may have confused myself a bit. I may redo it just to have it setup how I originally set it up , but I wouldn't know how how access the cameras variables like the way you had set it.

I originally had a seperate spatial and inner spatial for rotation and zooming, but noticed I can still rotate the camera if I parent it to the player, and rotate the player.

I clicked on the local space mode button but couldnt understand what it was doing.

Sorry, my bad. You need to change the code to something like this: func _physics_process(delta): var rightstickaxis = Vector2(Input.get_joy_axis(0,JOY_AXIS_0), Input.get_joy_axis(0, JOY_AXIS_1)) velocity.y += gravity * delta var move_dir = Vector3() "Movement on the Y axis -> Up and down" if rightstickaxis.y > 0: move_dir += camera.global_transform.basis.z.normalized() elif rightstickaxis.y < 0: move_dir -= camera.global_transform.basis.z.normalized() "Movement on the X axis -> Left and right" if rightstickaxis.y > 0: move_dir += camera.global_transform.basis.z.normalized() elif rightstickaxis.y < 0: move_dir -= camera.global_transform.basis.z.normalized() move_dir = move_dir.normalized() direction = move_dir * speed * delta if velocity.y > 0: gravity = -20 else: gravity = -30 velocity = move_and_slide(velocity, Vector3(0,1,0)) if is_on_floor() and Input.is_action_pressed("ui_accept"): velocity.y = 5

The reason the previous code wasn't working is because direction can have an X or Y value of zero, and multiplication by zero returns zero, which then nullifies any movement. The above code should (hopefully) work for joystick movement.


As for getting the camera node, there are several ways to do it. If the camera is a child of the player, then using get_node works fine. If it is not, then you can either use get_parent().get_node() if it is parented to the same node that the player is parented to, or you could use self.get_tree().root.get_node("whatever the top node is called").get_node("path to camera from top node").

Whatever works for you is what I'd go for.


As for local mode, I'll do my best to give a brief explanation (as it can be rather confusing):

When you open up the Godot editor and select a Spatial a gizmo pops up. Each of the arrows points towards the global world directions. When you move the Spatial around with the gizmo, you are moving the Spatial relative to the world's directional vector.

However, when you press the little cube button beside the snap button, the gizmo switches to local space mode. Now the arrows point relative to the rotation of the Spatial, the arrows are pointing to the Spatial's directional vectors. Each basis has three vectors, X, Y, and Z, and each of those vectors point towards each of the arrows that the gizmo shows in local space mode.

Hopefully that kinda makes sense. I still need to refine how I explain local directional vectors... :sweat_smile:

Thanks so much.

Would I need to equate velocity to the direction vector. The velocity isn't recieving anything but is set in the moveslide function. Also, when you mean moving up and down, do you mean on the z axis, as in moving forward and backward?

I added this to the code, and it flings backwards toward the camera.

	velocity.x = direction.x
	velocity.z = direction.z

Also I noticed you added move dir which is being equated to the direction speed delta. But as I said above theres no velocity being used other than for jump. again thanks for your help

Hmm, well I would have said to use the code you added... Though I'll admit I totally forgot to apply direction to velocity :cold_sweat:.

Also, when you mean moving up and down, do you mean on the Z axis, as in moving forward and backward Yeah, I mean forward and backwards. Sorry about that.


In an effort to find a solution, I have made a practice project. It works with a controller and is based on the kinematic character demo. It allows the camera to move around the character (and it's not parented to the character, so it shows how you can can get a node without it being parented), the character rotates towards the forward direction of the camera only when moving, and you can even zoom the camera in and out. Hopefully it will work for you :smiley:

Again thanks so much. It worked like a dream. I just changed some of the analog stick axis to make it play nicer.. The code also makes a lot of sense, much easier to understand without a lot of code. Appreciate it !! :smile: )

a year later

@winniethewind said: Again thanks so much. It worked like a dream. I just changed some of the analog stick axis to make it play nicer.. The code also makes a lot of sense, much easier to understand without a lot of code. Appreciate it !! :smile: )

Hi there! I dont know if you can help me too, I'm programing a basic 3th person camera, it works exactly like I want, but the problem is that it can pass through the meshes and I dont know how to fix it. Basically I want that the camera dont pass through them, like if the camera has also a collision shape (I try it by puting a collision shape to the node but it didn't work). To make you understand what I mean imagine any 3th person game jajaj.

Thank you very much!

4 years later