The object should rotate and move around a point (another object) in 3d. When the parent object rotates, the child object changes position in space, but remains stationary relative to the parent. If the parent object is moving, the child object is also moving. As if it were his child node. For example: parent - KinematicBody, "child" - StaticBody. I hope I explained it well. I tried to read the docs and google, but I couldn't find what I needed: a lot of broken code without explanation. Can you write a simple example? If possible, with an explanation. I found 2d example (not tested), but I don't understand how to change it to 3d. Thank you.
How to rotate one Spatial around another Spatial?
- Edited
You can use a Position3D as a child node to the parent object. https://docs.godotengine.org/en/stable/classes/class_position3d.html
Then on process/physics_process simply set the real child object to the position of the Position3D.
Or, if you don't need to do anything custom with the rotation, simply make the child object the child in the hierarchy (under the parent) and don't use Position3D, and it should work like you ask for.
Add and remove objects into the hierarchy dynamically? I tried, for some reason they disappear next to the parent, as if out of focus of the camera. But even the camera does not capture them from a long distance, this is some kind of strange bug.
Are you trying to make a 3D camera that will follow an object (like the player) but allow free rotation without the rotation of the object affecting it? If so, what I would recommend doing is having the Camera (and it's node) completely separate from the scene that contains the Player and then have the camera follow the character via code.
Something like this (untested, but I've used code similar many times):
# camera controller script
# Assumed tree structure:
# controller (script attached to this)
# -- Spatial (for rotation on one or more axes)
# -- -- Camera
#
# The rotation node needs to be at origin (0, 0, 0) relative to the instanced scene
# but the camera needs to have an offset on the Z axis, so when the camera rotation
# node rotates the camera will orbit the target node
extends Spatial
var camera_node : Camera
var camera_rotation : Spatial
# You will need to set this in the editor by clicking the node after creating the script. In the inspector you should be able to set it
export (NodePath) var path_to_target = null
# If doing it through code, just set target_node directly
var target_node : Spatial
func _ready():
if (path_to_target != null):
target_node = get_node(path_to_target)
func _process(delta):
# Rotate camera rotation node here or in _input! I'll leave the code out for this example
if (target_node != null):
global_transform.origin = target_node
Then all you need to do is set it to the node you want to follow, and it should work. If the target node rotates it will stay in place, but you can rotate it yourself. If you want, I can see about making a quick minimum example project when I have some spare time, just let me know if it would help :smile:
I need like this: https://kidscancode.org/godot_recipes/basics/rotation/ but don't use child nodes, because it will be dynamic
If you know the point you want to rotate around and the angle, you could get the position using some math (untested):
var angle : float = PI
var rotation_target_path
var rotation_target : Spatial
const DISTANCE_FROM_TARGET = 1.5
func _ready():
rotation_target = get_node(rotation_target_path)
func _process(delta):
# Just as an example - you may want to control this manually rather than have it just spin endlessly
angle += delta
var angle_vector = Vector2(cos(angle), sin(angle)
global_transform.origin = rotation_target.global_transform.origin
# I'm assuming you want to rotate relative to the XZ plane, so you rotate around the Y axis
# If you want to rotate on different axes, just change which values (x, y, z) you manipulate
global_transform.origin.x += angle_vector.x * DISTANCE_FROM_TARGET
global_transform.origin.z += angle_vector.z * DISTANCE_FROM_TARGET
This type of solution really will only work for rotating on a single axis, but it shouldn't require any additional nodes beyond the target node that you want to rotate around.
Thank you. It works like in that animation. Looks like I need to learn linear algebra to understand how to modify this for my needs.
Final worked code:
extends RigidBody
onready var player : KinematicBody = $"/root/TestGame/PlayerCube"
const BLOCK_SIZE = 0.002
var _positionOffset: Vector3
var _rotationOffset: Quat
func _ready():
_move_body(player.translation)
_set_offset(player.transform, transform)
func _process(delta):
var target_position = player.transform.origin - _positionOffset
var target_rotation = player.transform.basis.get_rotation_quat() * _rotationOffset
transform.origin = _rotate_around_pivot(target_position, player.transform.origin, target_rotation)
set_rotation(target_rotation.get_euler())
func _set_offset(pivot: Transform, subject: Transform):
_positionOffset = (pivot.origin - subject.origin)
_rotationOffset = pivot.basis.get_rotation_quat().inverse() * subject.basis.get_rotation_quat()
func _rotate_around_pivot(subject_position: Vector3, pivot: Vector3, subject_rotation: Quat):
return pivot + (subject_rotation * (subject_position - pivot))
func _move_body(trans):
translation.x = trans.x - BLOCK_SIZE * 2
translation.y = trans.y
translation.z = trans.z
I found this in stackoverflow question.
Thanks for the help, your code was useful to me too, there are many different behaviors in my game.
now I will figure out how it works, because it blows my mind ?