0 votes

I apologize if this has already been answered or is in the documentation, I've been looking in both for a long time but can't quite find what I'm looking for.

I want my camera to follow at a set distance from my character without rotating. Obviously as soon as make it a child of the player it follows at a set distance but also rotates and as soon as I make it a sibling, or separate it stays completely still.

(If it's hard to visualize think Crash Bandicoot, the camera never rotates but follows the player.)

(I have the movement as I want it with a non-rotating camera it's just making the camera follow that's the sticking point.)

I'm guessing I need to look here.


Set my camera relative to the player. Using a Vector3 offset. Or something along those lines.

Edit: More in comments.

in Engine by (15 points)
edited by

I've learnt how to get the exact global transform of the player using GDScript but of course this is no different than making the camera a child of the player in effect. How can I modify the following so it uses the x and y coordinates, changes the z and ignores any angles?

Is there a way to break up the get_global_transform / set_global_transform coordinates?

extends Camera
func _process(delta):   
  var PlayerLocation = get_node("/root/World/Player").get_global_transform()

The very bottom of this page talks about seperating the translation portion of Transform coordinates from the rotation portion but I don't understand how to implement it.


var t = Transform()
pos = t.xform(pos) # transform 3D position
pos = t.basis.xform(pos) # (only rotate)
pos = t.origin + pos # (only translate)

1 Answer

0 votes

First, I made some post in the godot developers forum about Physics and Transforms. For general reading:

This part of the post might help you with your question:

mycam.look_at_from_pos(Vector3(mycam.get_translation().x, \
         target.get_translation().y,mycam.get_translation().z), \

This is just the looking direction though. If you want to place the camera at some "2D" direction vector relative to the targets rotation you could split the targets transform.basis.

var target2DDir = Vector3(target.transform.basis.z.x,0, \

This code takes the direction Vector3 of the Z-Axis of the target object. (Which I assume as its "view" direction). Then it extracts the actual x and z coordinates of this axis.

You can take the resulting vector (maybe * -1), normalize it (--> length 1), and multiply it by the required camera distance. Than calculate the camera position by adding this to the target.transform.origin (=translation). If the target looks directly "up" or "down" this would set the camera directly on the target though.

By the way: You can (& should) omit get_node(".") when addressing own properties from the nodes own script. In places where you need an explicit reference to the instance/node (not here) you can use self.

Hope I understood your question

Oh, and if you want to move the camera in a smoother way then there's Tween and follow_property() as one possibility.

by (3,348 points)
edited by

Cool thanks for the response and link. Dealing with Vector3 coordinates and 3D Transforms isn't coming naturally to me to tell you the truth, I've gone back to 2D ones to try and get my head around things first.

No problem. Dealing with 3D transforms I always find myself making silly pilot-like movements, brain gets messed up, trying to sketch something on paper until i (hopefully) get there.

Sorry to dumb things way down but what is the proper syntax for .set_global_transform?

When I do:

func _ready():
    var GT = .get_global_transform()

    var zero = GT[0]
    var one = GT[1]
    var two = GT[2]
    var three = GT[3]

    print("Global Transform is ",GT)
    print("X is ", zero)
    print("Y is ", one)
    print("Z is ", two)
    print("Origin is ", three)

I get:

Global Transform is 1, 0, 0, 0, 1, 0, 0, 0, 1 - 0, 1.83918, 2.4662
X is (1, 0, 0)
Y is (0, 1, 0)
Z is (0, 0, 1)
Origin is (0, 1.83918, 2.4662)


^ Says:

Transform | Transform ( Vector3 x_axis, Vector3 y_axis, Vector3 z_axis, Vector3 origin )

So I thought I would write (if I hypothetically wanted to move a camera to the same place):

get_node("/root/Camera").set_global_transform(Transform (1, 0, 0), (0,1, 0), (0, 0, 1), (0, 1.83918, 2.4662))

But I get an error saying Expected ')' in expression

I can't find an example of someone actually using .set_global_transform with a string of coordinates written.

It works if I just do :


But not if I enter the actual characters of GT , either verbatim or in the syntax the docs say.

get_node("/root/Camera").set_global_transform( \
  Transform (Vector3(1, 0, 0), \
    Vector3(0,1, 0), Vector3(0, 0, 1), Vector3(0, 1.83918, 2.4662) \
   ) \

But you can also set/change parts of a spatials (or camera) transform:

 $"/root/Camera".global_transform.basis.x = Vector3(1,0,0)

(although setting a single basis vector generally makes no sense) or

 $"/root/Camera".transform.origin.x += 1.5

I started back at trying to fix this. If I do the following it prints the coordinates roughly were I want the camera to be, the same as the player but with only the x translate modified.
extends Camera

func _process(delta():

    var playerlocation = get_node("/root/World/Player").get_global_transform()
    print (playerlocation * Vector3 (2, 0, 0), Vector3 (0, 0, 0), Vector3 (1, 0, 0), Vector3 (0, 1, 0))

But I can't create a variable of it to actually use and apply to a camera I keep getting "Expected ')' in expression" no matter how I use the quotes.

var cameralocation = (playerlocation * Vector3 (2, 0, 0), Vector3 (0, 0, 0), Vector3 (1, 0, 0), Vector3 (0, 1, 0))

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.