Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add angular analogs of move_toward() #2074

Closed
UnwarySage opened this issue Jan 4, 2021 · 6 comments · Fixed by godotengine/godot#80225
Closed

Add angular analogs of move_toward() #2074

UnwarySage opened this issue Jan 4, 2021 · 6 comments · Fixed by godotengine/godot#80225
Milestone

Comments

@UnwarySage
Copy link

UnwarySage commented Jan 4, 2021

Describe the project you are working on

A top-down game, with automation of combatants through player made behavior trees.

Describe the problem or limitation you are having in your project

I'm making movement code for my top down characters, and I keep finding that Vector2 move_toward()
function is handy when moving kinematic bodies towards a point, but making them look at a point smoothly is hard.
look_at snaps something instantly, which isn't desired in this case.
Implementing and getting the wrapping logic took a chunk of brain power, to make sure it wasn't going to have subtle bugs with larger rotations, or negative ones.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Adding two functions to the core GDScript namespace, with the following WIP names.
rotate_toward(angle_a, angle_b, amount):
This takes three angles as floats, and returns angle_a, rotated towards angle_b, by amount, or less if angle_b can be reach in less than amount. This would perform wrapping around TAU, and moving along the shortest arc between a and b.

rotate_toward_degrees would be as above, but wrapping around 360 degrees instead, and could potentially be omitted.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Consider a topdown games turret. Having it move smoothly to look at a target could thus be.

var target_angle = (target_position - global_position).angle()
$TurretBase.global_rotation = rotate_toward($TurretBase.global_rotation, target_angle, turret_turn_speed)

Similar example could be used for top down vehicles, or burrowing/flying platformer enemies.

If this enhancement will not be used often, can it be worked around with a few lines of script?

It wouldn't be hard to write around with scripts, but it would be easy to get subtly wrong, and would potentially have to be repeated in many file throughout a project.,

Is there a reason why this should be core and not an add-on in the asset library?

Importing an add-on for this would be comparable to the amount of work required to do it in the first place. This aims to solve a papercut, like #42976 did.

Bugsquad edit, search terms: move_towards_angle

@Calinou Calinou changed the title Angular analogs of move_toward() Add angular analogs of move_toward() Jan 5, 2021
@KoBeWi
Copy link
Member

KoBeWi commented Jan 5, 2021

Did you try lerp_angle?

@UnwarySage
Copy link
Author

UnwarySage commented Jan 5, 2021 via email

@ettiSurreal
Copy link

Just ran into this problem as well, would like to add that this rotate_toward could also be added as a method to Float, Basis, Vector3(?) and Quaternion, similar to Unity.

@AncientSion
Copy link

this is exactly the issue that i need solved.

@UnwarySage can you give me your custom functions to solve your issue because this is exactly my problem (frame by frame rotation via lerp or angle lerp has a larger impact the more apart to angles are)

@nathanjf
Copy link

Here is a method I wrote that seems to work. I have it loaded on a global autoload called Utils in my game so I can just use it wherever I need it.

func move_toward_angle(from : float, to: float, delta : float):
	var ans = fposmod(to - from, TAU)
	if ans > PI:
		ans -= TAU
	return from + ans * delta

@Jamsers
Copy link

Jamsers commented Jul 23, 2023

Ran into the same issue and banged my head against it for the better part of the night (I am mathematically challenged 😅)
For those of you who are looking for an easy to use rotate_toward as well, here's the methods I ended up using, I like these cause they rely on slerp internally and therefore may handle the rotations as properly as slerp itself would:

func rotate_toward(from: Quaternion, to: Quaternion, delta: float) -> Quaternion:
	return from.slerp(to, min(1.0, delta / from.angle_to(to)))

func basis_rotate_toward(from: Basis, to: Basis, delta: float) -> Basis:
	return Basis(rotate_toward(from.get_rotation_quaternion(), to.get_rotation_quaternion(), delta))

Thanks to kleonc from Reddit for the solution ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants