Я копирую это из обмена математическим стеком по совету из комментария.
Вот код, с которого я начинаю:
func orientation_follow(state, current_basis : Basis, target_basis : Basis):
var delta : Basis = target_basis * current_basis.inverse();
var q = Quat(delta);
var axis = Vector3(q.x, q.y, q.z);
if (axis.length_squared() > 0.0001): # bullet fuzzyzero() is < FLT_EPSILON (1E-5)
axis = axis.normalized();
var angle = 2.0 * acos(q.w);
state.set_angular_velocity(axis * (angle / (state.get_step())));
else:
state.set_angular_velocity(Vector3(0,0,0));
Основа - это направление в котором каждый вектор объекта был повернут. Это инвертируется и умножается на основание целевого объекта (в данном случае контроллера движения игрока), чтобы получить дельта-вращение от объекта к контроллеру. Эта дельта преобразуется в кватернион, из которого ее ось получена и нормализована перед умножением арккозина на коэффициент z кватерниона на 2, чтобы получить угол и найти произведение угла на эту ось (деленное на время дельты, которое, я полагаю, немного сглаживает вращение), устанавливая скорость angular в соответствии с тем, как объекты RigidBody должны взаимодействовать в Godot.
По крайней мере, я так думаю.
проблема в том, что каждый раз, когда вы берете объект, он по существу привязывается к вращению контроллера, потому что функция интерполирует вращение объекта к вращению контроллера каждый кадр. Поэтому, если вы пытаетесь перевернуть что-то вверх дном, вы должны полностью повернуть свой контроллер, вместо того, чтобы поднимать его, класть его частично повернутым, а затем использовать другой контроллер для завершения вращения.
То, что я хотел бы сделать, это получить разницу во вращении в контроллере между последним и текущим кадром, а затем применить эту разницу к удерживаемому объекту в каждом кадре, но я ничего не пробовал в течение последнего Кажется, несколько часов работают. Конечная цель состоит в том, чтобы объект сохранял свое вращение при первоначальном захвате, но вращал ту же величину, что и контроллер, пока он удерживается, вместо того, чтобы сразу же привязываться к ориентации контроллера, как только он был поднят.
Редактировать: я нашел обходной путь (вместо этого используйте шарнирное соединение), поэтому нет необходимости в ответе на этот вопрос.