how to make the player mesh move, not with, but based on the camera's facing

empty_grimoireempty_grimoire Posts: 20Member

I am trying to make the character be able to move and rotate independent of the camera. moving forward moves the character towards where the character is facing. moving backwards would make it seem as though the player is running towards the real player, behind the camera. All the tutorials Ive seen tend to pack these two things together and as a beginner I can't begin to pick them apart. the camera is to be controlled with mouse movement, not clicks or drags but like in an FPS. Basically: an MMO style camera similar to black desert, cube world, dark souls. I can stitch together some aspects of certain tutorials together but I lack the glue and understanding. Might have to come back and get good, im Malding over here

«1

Comments

  • DschoonmakerDschoonmaker Posts: 242Member

    Do you have the camera script? It sounds like it's a third person camera?

  • empty_grimoireempty_grimoire Posts: 20Member

    Yes, for third person. For simplicity I'll also attach the whole file that comes from a tutorial with a good camera but lack of orbiting or "looking around" any direction automatically makes the player face that way. not what i desire here:
    extends KinematicBody

    export var speed : float = 20
    export var acceleration : float = 15
    export var air_acceleration : float = 5
    export var gravity : float = 0.98
    export var max_terminal_velocity : float = 54
    export var jump_power : float = 20
    
    export(float, 0.1, 1) var mouse_sensitivity : float = 0.3
    export(float, -90, 0) var min_pitch : float = -90
    export(float, 0, 90) var max_pitch : float = 90
    
    var velocity : Vector3
    var y_velocity : float
    #ive tried switching these around, changing what the pivot node is to no avail
    onready var camera_pivot = $CameraPivot
    onready var camera = $CameraPivot/CameraBoom/Camera
    
    func _ready():
        Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
    
    func _process(delta):
        if Input.is_action_just_pressed("ui_cancel"):
            Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    
    func _input(event):
        if event is InputEventMouseMotion:
            rotation_degrees.y -= event.relative.x * mouse_sensitivity
            camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
            camera_pivot.rotation_degrees.x = clamp(camera_pivot.rotation_degrees.x, min_pitch, max_pitch)
    
    func _physics_process(delta):
        handle_movement(delta)
    
    func handle_movement(delta):
        var direction = Vector3()
    
        if Input.is_action_pressed("move_forward"):
            direction -= transform.basis.z
    
        if Input.is_action_pressed("move_backward"):
            direction += transform.basis.z
    
        if Input.is_action_pressed("move_left"):
            direction -= transform.basis.x
    
        if Input.is_action_pressed("move_right"):
            direction += transform.basis.x
    
        direction = direction.normalized()
    
        var accel = acceleration if is_on_floor() else air_acceleration
        velocity = velocity.linear_interpolate(direction * speed, accel * delta)
    
        if is_on_floor():
            y_velocity = -0.01
        else:
            y_velocity = clamp(y_velocity - gravity, -max_terminal_velocity, max_terminal_velocity)
    
        if Input.is_action_just_pressed("jump") and is_on_floor():
            y_velocity = jump_power
    
        velocity.y = y_velocity
        velocity = move_and_slide(velocity, Vector3.UP)
    

    https://github.com/codewithtom/third-person-godot/tree/character-controller
    the only script is attached to the player. Ive asked a question similar to this before and one answer I got was to have a script attached to a camera instead that rotated it's parenting spacial (rig). I don't have the brains to implement the suggestion yet. the player file (the only one in the script), is set up as Player, with a spacial child, with a grandchild spring arm and finally a camera stemming from that arm.

  • empty_grimoireempty_grimoire Posts: 20Member

    @Dschoonmaker said:
    Do you have the camera script? It sounds like it's a third person camera?

  • DschoonmakerDschoonmaker Posts: 242Member

    I do it with two variables:

    var cameraAngle = Vector2.ZERO
    var cameraZoom = 2.25
    

    cameraAngle is a vector2, X is horizontal rotation and Y is vertical. cameraZoom is the distance the camera should be away from the player.

    I clamp them with:

    cameraAngle.x = fmod(cameraAngle.x, 2*PI)
    cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
    

    (X isn't clamped, but if the angle is greater than 360, it goes back to 0. Both 0.01s are just a small margin to prevent error.)

    and apply camera position with:

    X+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
    Z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
    Y+=cameraZoom*cos(cameraAngle.y)
    

    XY&Z should be the camera's XY&Z position, I shortened it to make it easier to read.

    Then for movement(I use a variable called moveDir, works the same as your direction), instead of something like this:

        moveDir.x -= Input.get_action_strength("p1_move_left")
    

    I have this:

        moveDir.x -= cos(cameraAngle.x)*Input.get_action_strength("p1_move_forward")
        moveDir.z -= sin(cameraAngle.x)*Input.get_action_strength("p1_move_forward")
        moveDir.x -= cos(cameraAngle.x+PI)*Input.get_action_strength("p1_move_backward")
        moveDir.z -= sin(cameraAngle.x+PI)*Input.get_action_strength("p1_move_backward")
        moveDir.x -= cos(cameraAngle.x+(270*PI/180))*Input.get_action_strength("p1_move_left")
        moveDir.z -= sin(cameraAngle.x+(270*PI/180))*Input.get_action_strength("p1_move_left")
        moveDir.x -= cos(cameraAngle.x+(90*PI/180))*Input.get_action_strength("p1_move_right")
        moveDir.z -= sin(cameraAngle.x+(90*PI/180))*Input.get_action_strength("p1_move_right")
    

    which handles movement in all directions(+ analog strength, works with joysticks). You probably don't need to understand this part, I've forgotten how exactly it works. But this code should do the trick.

    I also clamp moveDir:

        moveDir = Vector3(clamp(moveDir.x, -1, 1),clamp(moveDir.y, -1, 1),clamp(moveDir.z, -1, 1))
    

    I can explain more, tell me if you have any questions(and this is one method, I think I used another one in a different game).

  • empty_grimoireempty_grimoire Posts: 20Member

    Thanks for the reply. I will try this out. All of this script belongs to the camera script yes? input strength for joysticks wont conflict with key board presses either im guessing. I realize i worded the title of this to something quite misleading so im linking a video that quickly shows the desired movements. If your script mimics this system then I am golden.

    as I was typing out some of your lines I got an error for this line ; cameraAngle.x = fmod(cameraAngle.x, 2*PI)
    "unexpected token: identifier: cameraAngle"

  • DschoonmakerDschoonmaker Posts: 242Member

    I don't know why you get that error. I might need to see the code to find the problem.

    It's actually not in the camera script(at least the way I do it), I position the camera in the player script. So camera movement is handled in the player script(I do have a camera script, for smooth camera movement).

    It does do everything mentioned in the video.

  • empty_grimoireempty_grimoire Posts: 20Member
    edited June 27

    @Dschoonmaker said:
    I don't know why you get that error. I might need to see the code to find the problem.

    It's actually not in the camera script(at least the way I do it), I position the camera in the player script. So camera movement is handled in the player script(I do have a camera script, for smooth camera movement).

    It does do everything mentioned in the video.

    Here is the code to the player script , all of the entire project:

    extends KinematicBody
    #old variables
    export var speed : float = 20
    export var acceleration : float = 15
    export var air_acceleration : float = 5
    export var gravity : float = 0.98
    export var max_terminal_velocity : float = 54
    export var jump_power : float = 20
    
    export(float, 0.1, 1) var mouse_sensitivity : float = 0.3
    export(float, -90, 0) var min_pitch : float = -90
    export(float, 0, 90) var max_pitch : float = 90
    
    #define moveDir as Vector3
    var moveDir : Vector3
    var y_velocity : float
    
    onready var camera_pivot = $CameraPivot
    onready var camera = $CameraPivot/CameraBoom/Camera
    
    #new variables 
    var cameraAngle = Vector2.ZERO
    var cameraZoom = 2.25
    #the error here V
    X+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
    Z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
    Y+=cameraZoom*cos(cameraAngle.y)
    #clamping camera varibales
    cameraAngle.x = fmod(cameraAngle.x, 2*PI)
    cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
    
    
    #capturing mouse input
    func _ready():
        Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
    
    #making cursor visible on ui cancel
    func _process(delta):
        if Input.is_action_just_pressed("ui_cancel"):
            Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    
    
    #rotate camera with mouse input? probaly invalid now with new clamping variables
    func _input(event):
        if event is InputEventMouseMotion:
            rotation_degrees.y -= event.relative.x * mouse_sensitivity
            camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
            camera_pivot.rotation_degrees.x = clamp(camera_pivot.rotation_degrees.x, min_pitch, max_pitch)
    
    func _physics_process(delta):
        handle_movement(delta)
    
    func handle_movement(delta):
        #clamping moveDir
        moveDir = Vector3(clamp(moveDir.x, -1, 1),clamp(moveDir.y, -1, 1),clamp(moveDir.z, -1, 1))
        #moveDir
        moveDir.x -= cos(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.z -= sin(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.x -= cos(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.z -= sin(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.x -= cos(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.z -= sin(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.x -= cos(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        moveDir.z -= sin(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        direction = direction.normalized()
    
        var accel = acceleration if is_on_floor() else air_acceleration
        velocity = velocity.linear_interpolate(direction * speed, accel * delta)
    
        if is_on_floor():
            y_velocity = -0.01
        else:
            y_velocity = clamp(y_velocity - gravity, -max_terminal_velocity, max_terminal_velocity)
    
        if Input.is_action_just_pressed("jump") and is_on_floor():
            y_velocity = jump_power
    
        velocity.y = y_velocity
        velocity = move_and_slide(velocity, Vector3.UP)
    

    probably a mess. I added the code you provided to the tutorial project mentioned earlier. That could explain some of the problems. Honestly, I have a hard time understanding it all, gdscript in general. moveDir was never defined so i figured it would be a Vector3

  • DschoonmakerDschoonmaker Posts: 242Member
    #the error here V
    X+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
    Z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
    Y+=cameraZoom*cos(cameraAngle.y)
    #clamping camera varibales
    cameraAngle.x = fmod(cameraAngle.x, 2*PI)
    cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
    

    Your problem here is you call all of this outside any function. It should be in process or physics process(I have it in physics process, which is probably the right thing to do in my case because I have camera collisions), or some function called inside them; like your handle_movement()(I have update_camera()).

    Also, X Y & Z are not defined. If your camera is a child of the player node, you probably want this instead:

    cameraAngle.x = fmod(cameraAngle.x, 2*PI)
    cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
    #I have $Camera.translation now, $ means to get a child of this node.
    
    #I also switched the order of clamping and moving, it's good to clamp after
    #to avoid the camera moving where it shouldn't for a single frame.
    #I think I had it in this order in my code, but I explained it in the opposite order.
    
    $Camera.translation.x+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
    $Camera.translation.z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
    $Camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    

    moveDir is a Vector3, it's a variable used for changing velocity from input(like your direction).

  • empty_grimoireempty_grimoire Posts: 20Member
    edited June 27

    @Dschoonmaker node set up is
    Player (kinematic body)
    |_ cameraPivot (spatial) (also contains the current script)
    |_ cameraBoom (springarm)
    |_ camera (camera)
    |_ mesh Instance
    |_ collision shape.
    code now looks like this:

    extends KinematicBody
    #old variables
    export var speed : float = 20
    export var acceleration : float = 15
    export var air_acceleration : float = 5
    export var gravity : float = 0.98
    export var max_terminal_velocity : float = 54
    export var jump_power : float = 20
    export(float, 0.1, 1) var mouse_sensitivity : float = 0.3
    export(float, -90, 0) var min_pitch : float = -90
    export(float, 0, 90) var max_pitch : float = 90
    #define moveDir as Vector3
    var moveDir : Vector3
    var y_velocity : float
    onready var camera_pivot = $cameraRig
    onready var camera = $CameraPivot/CameraBoom/Camera
    #new variables
    var cameraAngle = Vector2.ZERO
    var cameraZoom = 2.25
    #defining x, y, z
    var X = Vector3(1,0,0)
    var Y = Vector3(0,1,0)
    var Z = Vector3(0,0,1)
    
    #clamping camera variables
    #capturing mouse input
    func _ready():
        Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
    #making cursor visible on ui cancel
    func _process(delta):
        if Input.is_action_just_pressed("ui_cancel"):
            Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    #getting errors here now, compiler doesn't know what rotation_degrees is. I thought that was built in. 
    func _input(event):
        if event is InputEventMouseMotion:
            rotation_degrees.y -= event.relative.x * mouse_sensitivity
            camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
            camera_pivot.rotation_degrees.x = clamp(camera_pivot.rotation_degrees.x, min_pitch, max_pitch)
    func _physics_process(delta):
        handle_movement(delta)
        update_camera()
    
    
    func update_camera():
        cameraAngle.x = fmod(cameraAngle.x, 2*PI)
        cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
        #X+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
        #Z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
        #Y+=cameraZoom*cos(cameraAngle.y)
    
        $Camera.translation.x+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
        $Camera.translation.z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
        $Camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    func handle_movement(delta):
        #clamping moveDir
        moveDir = Vector3(clamp(moveDir.x, -1, 1),clamp(moveDir.y, -1, 1),clamp(moveDir.z, -1, 1))
        #moveDir
        moveDir.x -= cos(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.z -= sin(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.x -= cos(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.z -= sin(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.x -= cos(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.z -= sin(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.x -= cos(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        moveDir.z -= sin(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        moveDir = moveDir.normalized()
        var accel = acceleration if is_on_floor() else air_acceleration
        moveDir = moveDir.linear_interpolate(moveDir * speed, accel * delta)
        if is_on_floor():
            y_velocity = -0.01
        else:
            y_velocity = clamp(y_velocity - gravity, -max_terminal_velocity, max_terminal_velocity)
        if Input.is_action_just_pressed("jump") and is_on_floor():
            y_velocity = jump_power
    
        moveDir.y = y_velocity
        moveDir = move_and_slide(moveDir, Vector3.UP)
    

    I think the camera rotation from this script is broken now.

  • DschoonmakerDschoonmaker Posts: 242Member

    You have X Y & Z as variables. They should be references to the camera's X Y & Z position. For example, X should be $camera.translation.x.

  • empty_grimoireempty_grimoire Posts: 20Member
    edited June 28

    @Dschoonmaker said:
    You have X Y & Z as variables. They should be references to the camera's X Y & Z position. For example, X should be $camera.translation.x.

    Okay. Ive changed the code in func camera to:

     func update_camera():
            cameraAngle.x = fmod(cameraAngle.x, 2*PI)
            cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
            $camera.translation.x=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
            $camera.translation.z=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
            $camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    
            $Camera.translation.x+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
            $Camera.translation.z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
            $Camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    

    or did you mean: X = $camera.translation.x ?

  • DschoonmakerDschoonmaker Posts: 242Member

    Oh, you did have it. I was looking at the code you commented out. Also, I forgot to add one crucial line before the camera position gets modified:

    $Camera.translation = Vector3.ZERO
    

    The camera position needs to be reset, because the camera movement code adds to its position. In my game, I have a variable called cameraOffset:

    $Camera.translation = cameraOffset
    

    it's a Vector3, it offsets the position of the camera. Usually it looks good to have the camera focus a little above the player's head, so in my case I have it set to:

    cameraOffset = Vector3.UP*1.5
    

    or

    cameraOffset = Vector3(0,1.5,0)
    

    But cameraOffset isn't necessary, if it looks good without it you probably don't need it.

  • empty_grimoireempty_grimoire Posts: 20Member

    when I implement this line of code: $Camera.translation = Vector3.ZERO within my update_camera function, i get the error invalid set index 'translation' (on base: null instance) with value of type 'Vector3.'

    entire code looks like this now:

    extends KinematicBody
    #old variables
    export var speed : float = 20
    export var acceleration : float = 15
    export var air_acceleration : float = 5
    export var gravity : float = 0.98
    export var max_terminal_velocity : float = 54
    export var jump_power : float = 20
    export(float, 0.1, 1) var mouse_sensitivity : float = 0.3
    export(float, -90, 0) var min_pitch : float = -90
    export(float, 0, 90) var max_pitch : float = 90
    #define moveDir as Vector3
    var moveDir : Vector3
    var y_velocity : float
    onready var camera_pivot = $cameraRig
    onready var camera = $cameraRig/SpringArm/Camera
    #new variables
    var cameraAngle = Vector2.ZERO
    var cameraZoom = 2.25
    var cameraOffset = Vector3(0,1.5,0)
    #the error here V
    
    #clamping camera varibales
    #capturing mouse input
    func _ready():
        Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
    #making cursor visible on ui cancel
    func _process(delta):
        if Input.is_action_just_pressed("ui_cancel"):
            Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    #rotate camera with mouse input? probaly invalid now with new clamping variables
    func _input(event):
        if event is InputEventMouseMotion:
            rotation_degrees.y -= event.relative.x * mouse_sensitivity
            camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
            camera_pivot.rotation_degrees.x = clamp(camera_pivot.rotation_degrees.x, min_pitch, max_pitch)
    func _physics_process(delta):
        handle_movement(delta)
        update_camera()
    
    
    func update_camera():
        cameraAngle.x = fmod(cameraAngle.x, 2*PI)
        cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
        $Camera.translation = Vector3.ZERO
        #X+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
        #Z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
        #Y+=cameraZoom*cos(cameraAngle.y)
    
        $Camera.translation.x+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
        $Camera.translation.z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
        $Camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    
    func handle_movement(delta):
        #clamping moveDir
        moveDir = Vector3(clamp(moveDir.x, -1, 1),clamp(moveDir.y, -1, 1),clamp(moveDir.z, -1, 1))
        #moveDir
        moveDir.x -= cos(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.z -= sin(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.x -= cos(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.z -= sin(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.x -= cos(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.z -= sin(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.x -= cos(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        moveDir.z -= sin(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        moveDir = moveDir.normalized()
        var accel = acceleration if is_on_floor() else air_acceleration
        moveDir = moveDir.linear_interpolate(moveDir * speed, accel * delta)
    
        if is_on_floor():
            y_velocity = -0.01
        else:
            y_velocity = clamp(y_velocity - gravity, -max_terminal_velocity, max_terminal_velocity)
        if Input.is_action_just_pressed("jump") and is_on_floor():
            y_velocity = jump_power
    
        moveDir.y = y_velocity
        moveDir = move_and_slide(moveDir, Vector3.UP)
    
  • DschoonmakerDschoonmaker Posts: 242Member

    Camera should be a child node of the player(I'm just clarifying, it looks like you have it that way already). Also, is the name of your camera node "Camera"? With a capital C(it's case sensitive)?

  • empty_grimoireempty_grimoire Posts: 20Member

    @Dschoonmaker said:
    Camera should be a child node of the player(I'm just clarifying, it looks like you have it that way already). Also, is the name of your camera node "Camera"? With a capital C(it's case sensitive)?

    yes. the name of the spatial, which is the first root node of this scene involving the player, is "player" and the camera is a child of it. And it is also spelled that way. with the capital C and all. Does the hierarchy of the nodes matter? I have the camera coming before the kinematic body from top to bottom

  • MegalomaniakMegalomaniak Posts: 2,654Admin

    I would probably have the kinematic body above the camera, but depending on what you are going for maybe your way makes some sense? I'm not sure why you'd wan't to have the camera above though.

    Wait, are all your nodes on the same level? You might want some actually parented to others, for an example camera to camera boom.

    The order of nodes in the sceenetree does matter, especially when it comes to 2D since things are drawn in an order defined by it.

  • TwistedTwiglegTwistedTwigleg Posts: 2,666Admin

    Additionally, remember that any nodes parented to another nodes will inherit their transform. This is great for things like a Camera boom, as Megalomaniak mentioned, but remember not to parent nodes you want to have separate transforms. Since you want the Camera and the player to have two separate transforms, you will need to make sure the Camera is not a child of the player, as otherwise it will inherit any changes to rotation/position/scale made to the player.

  • empty_grimoireempty_grimoire Posts: 20Member

    @TwistedTwigleg said:
    Additionally, remember that any nodes parented to another nodes will inherit their transform. This is great for things like a Camera boom, as Megalomaniak mentioned, but remember not to parent nodes you want to have separate transforms. Since you want the Camera and the player to have two separate transforms, you will need to make sure the Camera is not a child of the player, as otherwise it will inherit any changes to rotation/position/scale made to the player.

    Okay. I have the camera, as a child of the root (spatial) and not the kinematic body which is also attached to the spatial. Is this viable or will the camera have to have its own scene attached to the world, separate from the kinematic body?

  • TwistedTwiglegTwistedTwigleg Posts: 2,666Admin

    @empty_grimoire said:

    @TwistedTwigleg said:
    Additionally, remember that any nodes parented to another nodes will inherit their transform. This is great for things like a Camera boom, as Megalomaniak mentioned, but remember not to parent nodes you want to have separate transforms. Since you want the Camera and the player to have two separate transforms, you will need to make sure the Camera is not a child of the player, as otherwise it will inherit any changes to rotation/position/scale made to the player.

    Okay. I have the camera, as a child of the root (spatial) and not the kinematic body which is also attached to the spatial. Is this viable or will the camera have to have its own scene attached to the world, separate from the kinematic body?

    Yup, that should be viable! As long as it is separate from the KinematicBody, it shouldn’t be affected by the KinematicBody’s rotation.

  • DschoonmakerDschoonmaker Posts: 242Member

    There's a function called node.set_as_toplevel(), if you put true inside the parentheses, the node will be set as "top level". That way, you can have a node as a child of another node, but it won't inherit position or rotation from any of its parents. I don't use it for my camera, but it is useful to know(I don't need it, I rotate the camera with look_at()).

    You haven't fixed the camera yet, right? What problem are you currently working on?

  • empty_grimoireempty_grimoire Posts: 20Member

    @Dschoonmaker I haven't made much progress. I get an error. On line 34-36. The function that controls camera rotation with mouse movement. rotation_degrees.y -= event.relative.x * mouse_sensitivity camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
    "invalid get index 'rotation_degrees' on base : ( 'null instance')
    I think my previous code conflicts with the insightful suggestions I've been given I am not sure. I'm trying to do things on step at a time. make the player turn when they move, make the camera rotate with mouse etc.

  • DschoonmakerDschoonmaker Posts: 242Member

    Is camera_pivot a variable? If so, can you show me the line where you declare it? If not, I guess that you're trying to reference a child of the player node. If so, you can get a child with $, so this:

    camera_pivot.rotation_degrees.x
    

    should be this:

    $camera_pivot.rotation_degrees.x
    

    $ only works for getting children, though. I'm assuming that camera_pivot is a child of the player node, and that camera_pivot is a node itself.

  • empty_grimoireempty_grimoire Posts: 20Member

    @Dschoonmaker said:
    Is camera_pivot a variable? If so, can you show me the line where you declare it? If not, I guess that you're trying to reference a child of the player node. If so, you can get a child with $, so this:

    camera_pivot.rotation_degrees.x

    should be this:

    $camera_pivot.rotation_degrees.x

    $ only works for getting children, though. I'm assuming that camera_pivot is a child of the player node, and that camera_pivot is a node itself.

    I think you are right. It is a variable defined as so: onready var camera = $cameraRig/SpringArm/Camera and I didn't have the $ preceding it. I will try this.

  • empty_grimoireempty_grimoire Posts: 20Member

    @Dschoonmaker I tried the fix and it didn't fix the issue, the error still remains

  • DschoonmakerDschoonmaker Posts: 242Member

    Can I see your code?

  • empty_grimoireempty_grimoire Posts: 20Member
    edited July 7

    @Dschoonmaker said:
    Can I see your code?

    absolutely. and for whatever reason when I preview this message it looks very strange so sorry for that.

    extends KinematicBody
    #old variables
    export var speed : float = 20
    export var acceleration : float = 15
    export var air_acceleration : float = 5
    export var gravity : float = 0.98
    export var max_terminal_velocity : float = 54
    export var jump_power : float = 20
    export(float, 0.1, 1) var mouse_sensitivity : float = 0.3
    export(float, -90, 0) var min_pitch : float = -90
    export(float, 0, 90) var max_pitch : float = 90
    
    var moveDir : Vector3
    var y_velocity : float
    onready var camera_pivot = $player
    onready var camera = $cameraRig/SpringArm/Camera
    #new variables
    var cameraAngle = Vector2.ZERO
    var cameraZoom = 2.25
    var cameraOffset = Vector3(0,1.5,0)
    
    #clamping camera varibales
    #capturing mouse input
    func _ready():
        Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
    #making cursor visible on ui cancel
    
    func _process(delta):
        if Input.is_action_just_pressed("ui_cancel"):
            Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    #rotate camera with mouse input?
    
    func _input(event):
        if event is InputEventMouseMotion:
            rotation_degrees.y -= event.relative.x * mouse_sensitivity
            $camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
            $camera_pivot.rotation_degrees.x = clamp(camera_pivot.rotation_degrees.x, min_pitch, max_pitch)
    func _physics_process(delta):
        handle_movement(delta)
        update_camera()
    
    
    func update_camera():
        cameraAngle.x = fmod(cameraAngle.x, 2*PI)
        cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
        $Camera.translation = Vector3.ZERO
        #X+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
        #Z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
        #Y+=cameraZoom*cos(cameraAngle.y)
    
        $Camera.translation.x+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
        $Camera.translation.z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
        $Camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    
    func handle_movement(delta):
        #clamping moveDir
        moveDir = Vector3(clamp(moveDir.x, -1, 1),clamp(moveDir.y, -1, 1),clamp(moveDir.z, -1, 1))
        #moveDir
        moveDir.x -= cos(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.z -= sin(cameraAngle.x)*Input.get_action_strength("move_forward")
        moveDir.x -= cos(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.z -= sin(cameraAngle.x+PI)*Input.get_action_strength("move_backward")
        moveDir.x -= cos(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.z -= sin(cameraAngle.x+(270*PI/180))*Input.get_action_strength("move_left")
        moveDir.x -= cos(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        moveDir.z -= sin(cameraAngle.x+(90*PI/180))*Input.get_action_strength("move_right")
        moveDir = moveDir.normalized()
        var accel = acceleration if is_on_floor() else air_acceleration
        moveDir = moveDir.linear_interpolate(moveDir * speed, accel * delta)
    
        if is_on_floor():
            y_velocity = -0.01
        else:
            y_velocity = clamp(y_velocity - gravity, -max_terminal_velocity, max_terminal_velocity)
        if Input.is_action_just_pressed("jump") and is_on_floor():
            y_velocity = jump_power
    
        moveDir.y = y_velocity
        moveDir = move_and_slide(moveDir, Vector3.UP)
    
  • MegalomaniakMegalomaniak Posts: 2,654Admin

    Fixed the code formatting in your post.

  • DschoonmakerDschoonmaker Posts: 242Member

    Two things:

    You're not updating cameraAngle. It looks like you rotate a node based on mouse movement, instead you should be changing cameraAngle. This should work:

    func _input(event):
        if event is InputEventMouseMotion:
            cameraAngle.x += event.relative.x
            cameraAngle.y += event.relative.y
    

    Second, in the part where you move the camera, the camera's position needs to be set before changing the camera position. I set it to cameraOffset, so that the camera orbits around cameraOffset instead of Vector3(0,0,0).

    $Camera.translation = cameraOffset
    $Camera.translation.x+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
    $Camera.translation.z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
    $Camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    

    Those are the only two problems I found, I think it should work after you fix these.

  • empty_grimoireempty_grimoire Posts: 20Member
    edited July 9

    @Dschoonmaker
    I've made the changes you suggested and I now have an error on the $Camera.translation = cameraOffset line. It reads: Invalid set index 'translation' (on base: 'null instance') with value type 'Vector3'. I still have CameraOffset defined at the top.

    func _physics_process(delta):
        handle_movement(delta)
        update_camera()
    
    func update_camera():
        cameraAngle.x = fmod(cameraAngle.x, 2*PI)
        cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
        $Camera.translation = cameraOffset
    
        $Camera.translation.x+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
        $Camera.translation.z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
        $Camera.translation.y+=cameraZoom*cos(cameraAngle.y)
    
  • DschoonmakerDschoonmaker Posts: 242Member

    Is "Camera"(case sensitive) a direct child of the node with this script? It looks like it knows cameraOffset is a Vector3, so I think the problem is with $Camera.translation.

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file