I have a very basic setup for a 3d character controller with a camera. This is kept basic to explain my question.
The Setup
Level.tscn Level (Spatial node with Level.gd) - CameraAnchor (Position3D node) - Camera (Camera Node) - Ground (CSGBox node)
Level.gd:
extends Spatial
export(PackedScene) var playerPack
onready var cam = $CameraAnchor
var pawns : Array
var activePawn : Spatial
func _ready():
populateLevel(4)
activePawn = pawns[0]
activePawn.isActive = true
func _process(delta):
handleInput()
moveCamera()
func moveCamera():
cam.transform.origin = activePawn.transform.origin
func setNewActive(ID : int):
ID -= 1 #array starts at 0
if pawns[ID]:
activePawn.isActive = false
activePawn = pawns[ID]
activePawn.isActive = true
func handleInput():
if Input.is_action_just_pressed("one"):
setNewActive(1)
elif Input.is_action_just_pressed("two"):
setNewActive(2)
elif Input.is_action_just_pressed("three"):
setNewActive(3)
elif Input.is_action_just_pressed("four"):
setNewActive(4)
func populateLevel(amount : int):
pawns = []
pawns.resize(amount)
for i in amount:
pawns[i] = playerPack.instance()
add_child(pawns[i])
pawns[i].transform.origin.x = i * 3
Player.tscn Player (KinematicBody node with Player.gd) - Body (MeshInstance node) - Goggles (MeshInstance node)
Player.gd:
extends KinematicBody
var isActive = false
var speed = 500
var velocity = Vector3.ZERO
func _process(delta):
if isActive:
handleInput()
move_and_slide(velocity.normalized() * speed * delta)
func handleInput():
velocity = Vector3.ZERO
if Input.is_action_pressed("left"):
velocity.x -= 1
if Input.is_action_pressed("right"):
velocity.x += 1
if Input.is_action_pressed("up"):
velocity.z -= 1
if Input.is_action_pressed("down"):
velocity.z += 1
The Problem
When the player moves the camera follows its position, however first the Level.gd updates and moves the camera to the position of the player. After this, player.gd updates and moves the player. This causes the player to seem jittery and not stay in the middle of view when moving.
Possible Solutions
I could try to replace the process(delta) in player.gd with a custom update function and call that in Level.gd before moveCamera(). But then I would need to replace all process(delta) function in scripts where the camera would be able to focus on.
I could reparent the $CameraAnchor to the active player. But then I would have to reparent it everytime I moved the camera focus to a new entity. Also this would make it difficult to have the camera zoom and focus on multiple players on screen in the future.
Desired Solution
As in the example code above I am looking for a solution that is ready for easy switching between entities. Later on I might even add switching to focus view of enviroment or multiple players at once, and even lerp between them. For this it seems like a bad idea to parent the $CameraAnchor to an entity. However pretty much all tutorials I can find use the parenting technique.
Does anyone know of a possible solution? Or maybe some tutorial or example code I could look into?