Векторная математическая задача Unity3D для настройки Aim с использованием IK

#c# #unity3d

#c# #unity3d

Вопрос:

По сути, я использую систему Ik в Unity, и я хочу, чтобы мой пистолет был нацелен на мышь. Проблема в том, что я могу контролировать только положение кости IK, из которой не вылетит пуля, есть объект Gun, который является дочерним элементом кости IK, и он вращается вместе с ним. Что я хочу сделать, так это расположить IK таким образом, чтобы точка огня (где вылетит пуля) всегда была повернута к мыши.

Вот изображение, чтобы лучше визуализировать проблему Настройка Aim

Комментарии:

1. У вас есть gameobject или что-нибудь в firePoint ? Из диаграммы видно, что есть один at firePoint с его локальным правым (красная ось), указывающим из пистолета. Это правильно?

2. Да, игровой объект называется firePoint, но я не могу контролировать его положение, только ik-кость. и это дочерний элемент пистолета.

3. И, просто чтобы подтвердить — правильное направление указывает на направление стрельбы? Это очень необычно для 3D-игры, и вопрос на самом деле не указывает, является ли это 2d или 3d-игрой.

4. Да, он находится в 2D, и его правильное направление вращается вместе с пистолетом. и пистолет сам вращается в зависимости от ik.

5. Итак, если пистолет направлен влево — он все равно стреляет в локальном правильном направлении? Добавляю ответ сейчас.

Ответ №1:

Объяснение в комментариях

 // currentFirePoint and currentIKPoint are the transform of the fire Point and the 
// world position of IK Point at some given moment. 
// aimOrign and mousePosInWorldSpace are world space positions of the aim Origin and 
// mouse position that produce the desired IK point.
Vector3 GetNewIKPoint(Transform currentFirePoint, Vector3 currentIKPoint,
        Vector3 aimOrigin, Vector3 mousePosInWorldSpace)
{
    float firePointRange = aimOriginToCurrentFP.magnitude;

    //Find the local position of IK in Fire Point space
    Vector3 curFirePointToIK = currentIKPoint - currentFirePoint;
    Vector3 localFirePointToIK = currentFirePoint.InverseTransformVector(
            curFirePointToIK);

    // Stuff above this point could be done once and cached, 
    // assuming things like the offset or fire point range don't change.
    
    // Determine where the new fire point will be
    Vector3 newFireDirection = (mousePosInWorldSpace - aimOrigin).normalized;
    Vector3 newFirePoint = firePointRange * newFireDirection;

    // Find rotation such that local right = newFireDirection
    // and local up is closer to Vector3.up than Vector3.down

    // find local forward
    Vector3 newFPLocalForward = Vector3.Cross(newFireDirection, Vector3.up);
    // find local up
    Vector3 newFPLocalUp = Vector3.Cross(newFPLocalForward, newFireDirection);
    Quaternion newFPRotation = Quaternion.LookRotation(newFPLocalForward, 
            newFPLocalUp);

    // Apply that rotation to the local position of IK to find the world space offset. 
    Vector3 newFirePointToIK = newFPRotation * localFirePointToIK;

    // Add to fire point to get world space position
    return newFirePoint   newFirePointToIK;
}
 

Эта же логика может быть применена и к пространству 3D, но не забудьте newFPRotation соответствующим образом изменить вычисление.