0 votes

First, here is my goal:

I want a 3D orthographic camera to "tweenly" rotate (by user control) around a pivot point that is parented to the player avatar (In this case, a ship. But that isn't important.) The intended effect is something like a 2D isometric game with full camera rotation. To be clear, this is all 3D made to look almost like 2D.

Here is my problem:

When the pivot point crosses over from positive to negative the Tween node flips the camera around in the opposite direction. In degrees; it switches from 180 to -180 and when I do it in radians; it switches from π to -π (obviously). When that crossover from positive to negative happens, the camera does (almost) a full spin. The camera should just cross over that positive/negative boundary without going back the other way. Hopefully, that makes enough sense that someone out there knows what I'm talking about.

Here is my node graph:

Player (Spatial)

    Ship (RigidBody)

        CameraRig_0 (Position3D)

    CameraRig_1 (Position3D)

        CameraTween_1 (Tween)

        CameraRig_2 (Position3D)

            CameraTween_2 (Tween)

            Camera (Camera, set as "Current")

        CameraRig_2_Target (Position3D)

"Ship" has code that is not pertinent to the camera other than its coordinates, which are taken from its child "CameraRig_0".

"CameraRig_1" has this code:

extends Position3D

export var tween_time = 0.05

onready var cam_tween = get_node("CameraTween_1")

func _process(delta):

    var strt_vect = self.global_transform.origin
    var tgt_vect = $"../Ship/CameraRig_0".global_transform.origin

    cam_tween.interpolate_property(self, "translation", strt_vect, tgt_vect, tween_time, Tween.TRANS_BOUNCE, Tween.EASE_IN)
    cam_tween.start()

That code works (for whatever reason) to make the camera follow the ship in a way that feels right. Now, on to the problem areas involving rotation. "CameraRig_2" has this code:

extends Position3D

export var tween_time = 0.1

onready var cam_tween = get_node("CameraTween_2")

func _process(delta):

    var strt_rot = self.rotation
    var tgt_rot = $"../CameraRig_2_Target".rotation

    #debugging:
    print(tgt_rot) # Problem: Target switches from positive to negative so the tween flips around.

    cam_tween.interpolate_property(self, "rotation", strt_rot, tgt_rot, tween_time, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
    cam_tween.start()

And then the simplest part: "CameraRig2Target" has this code:

extends Position3D

var cam_rot_spd = 0.03

func _process(delta):

    if Input.is_action_pressed("h_camleft"):
        rotate_y(cam_rot_spd)

    if Input.is_action_pressed("h_camright"):
        rotate_y(-cam_rot_spd)

I could just use that last code and it would work just fine. But I want to be able to use the tweening without worrying about the tweening going in the wrong direction and creating that undesirable "spin" effect.

I'm sure that someone out there knows what I am trying to do, and they also know that I'm going about it in a 'bass-ackwards' way. I just need someone out there to set me on the right track.

Godot version v3.2.3.stable.flathub
in Engine by (12 points)

Here is a link to a gif that will probably make the problem easier to understand:

https://photos.app.goo.gl/h3Dfz3ukdMdjqY5P6

1 Answer

0 votes

from the docs:
Tween: Smoothly animates a node's properties over time.

i think that by definition you cannot do value jumps with tweens, as they are made to interpolate 2 values, if one is positive and the other is negative, they will lineary go from positive to negative.
either you never reset the angle, or you do it in one frame, something like

if rotation>180:
 rotation-=180
by (1,436 points)

You're right. Tweening was not what I wanted to use. (I'm still new to this.)

What I really wanted was 'slerping.' I found this page in the docs:

https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html#interpolating-with-quaternions

I basically used that exact same code and it worked great!

extends Position3D

export var slerp_amount = 0.2

func _process(delta):

    var strt_rot = Quat(self.transform.basis)
    var tgt_rot = Quat($"../CameraRig_2_Target".transform.basis)
    var slerp_to = strt_rot.slerp(tgt_rot,slerp_amount)
    transform.basis = Basis(slerp_to)

i actually have to thank you, i didnt know about the slerp function and it'll be very usefull for my project :)

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 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 webmaster@godotengine.org with your username.