Я хотел бы переместить объект вокруг другого - как если бы один объект был дочерним по отношению к другому. Это GDscript - Godot Engine 3.2, но логика c должна быть очень похожа на другие игровые движки.
Всякий раз, когда я держу пробел, зеленый куб следует за вращением синих кубов.
Первый GIF демонстрирует зеленый куб, начиная с позиции Vector3 (0, 4, 0) без поворота. Это прекрасно работает.
Во втором GIF я несколько раз удерживаю и отпускаю пробел. Я бы ожидал, что зеленый куб продолжит с того места, где он ушел, но вместо этого он "прыгнет" на новую позицию и продолжит оттуда.
![enter image description here](https://i.stack.imgur.com/ZrQ8E.gif)
![enter image description here](https://i.stack.imgur.com/cp79W.gif)
Код ниже не включает фактическое вращение синего куба (точки вращения), а только вычисления, необходимые для перемещения / вращения зеленого куба. Вращение синего куба не проблема. Кроме того, вращение просто ради демонстрации - в реальном сценарии синий куб тоже будет двигаться.
Вращения рассчитываются с использованием кватерниона, но это не является обязательным требованием.
extends Node
var _parent
var _child
var _subject
var _positionOffset: Vector3
var _rotationOffset: Quat
func _ready():
_parent = get_parent()
_child = $"/root/Main/Child"
func _input(event):
if event is InputEventKey:
if event.scancode == KEY_SPACE:
if event.is_action_pressed("ui_accept") and _child != null:
_subject = _child
_set_subject_offset(_parent.transform, _child.transform)
elif event.is_action_released("ui_accept"):
_subject = null
func _set_subject_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 _physics_process(_delta):
if _subject == null: return
var target_position = _parent.transform.origin - _positionOffset
var target_rotation = _parent.transform.basis.get_rotation_quat() * _rotationOffset
_subject.transform.origin = _rotate_around_pivot(target_position, _parent.transform.origin, target_rotation)
_subject.set_rotation(target_rotation.get_euler())
Я чувствую, что упускаю что-то очевидное.