0 votes

Here are my code with comments:

extends Spatial
var min_distance = 5
var max_distance = 10
func _process(delta):
    var target = get_node("../ObjectB")
#   get global transforms
    var target_t: Transform = target.get_global_transform_interpolated()
    var own_t: Transform = get_global_transform_interpolated()
#   get offset (direction and length) from target (origin) to follower position
    var offset = own_t.origin - target_t.origin
#   if offset length is not within minimum and maximum distances
    if offset.length() > max_distance:
        offset = offset.normalized() * max_distance
    if offset.length() < min_distance:
        offset = offset.normalized() * min_distance
#   normalize offset to know only direction
    var normalized_offset = offset.normalized()
#   get dot product of same two vectors to know the angle between them
#   (z axis points to the same direction as object's face)
    var dot = target_t.basis.z.dot(normalized_offset)
#   get cross product of z axis and offset and normalize it
#   to know in which direction rotate offset vector 
#   (order of operation matters)
    var normal = normalized_offset.cross(target_t.basis.z).normalized()
#   cross product will return (0,0,0) if two vectors are aligned
#   and it won't be possible to use the reslut of the cross product as axis
    if normal != Vector3.ZERO:
#       get rad angle from the result of the dot product
#       and rotate offset along normal axis
#       (if rotate not with additional PI, offset and z axis will be aligned 
#       and follower will be in front of target, because offset is a vector
#       from target position to follower position)
        offset = offset.rotated(normal, PI + acos(dot))
#   find new follower position by adding vector facing follower to target position
    var new_position: Vector3 = target_t.origin + offset
#   gradually move to new position
    new_position = lerp(own_t.origin, new_position, 0.05)
#   change follower position and rotation
    look_at_from_position(new_position, target_t.origin, Vector3.UP)

I am new to Godot. Is there a built-in tool or some option for that? I wrote it for a camera, changing the Godot's vehicle example.

Godot version 3.5.1
in Engine by (28 points)
edited by

I haven't looked much at your code, but I definitely wouldn't do that get_node() call inside _process(). That result won't change, so there's no reason to waste cycles looking it up in every frame. Look it up once (likely in _ready() or as an onready var) and use it as necessary.

Perhaps it could be made easier with RemoteTransform node. Can You elaborate some more on how this following is supposed to work in your project ?

A camera follows a car in some allowed distance range. And there is an angle where camera starts react if the car's direction changes. I didn't add it in the code above, but I achieved this with this additional check "if normal != Vector3.ZERO && acos(dot) < PI - maxbehindangle". The lerp function gives a lag when the camera starts react if the car moves or rotates, and this gives more natural movements. Of course, the most simple solution is to set the camera as a child to the car, but it looks bad. Ideally the distance between the camera and the car should change according to speed of the car. But I haven't implemented this yet, because maybe there is a much simpler solution to make a following camera with some node.

hehe, sorry, this sounds complicated enough to require complicated 3d math and few lines of code :)
RemoteControl or childing camera to some Pivot with some tweaks would eventually be easy and simple sollution, but You would never be able to improve this sollution the way You are designing now

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.