为逆运动系统添加平行偏移的优化解决方案

问题描述 投票:0回答:0

我正在游戏中实现一个反向运动学系统(基于 Alan Zucconi 的 IK 教程和代码),尽管该系统按原样完美运行,但我想包括“抵消”基于附加到系统末端的对象的系统。

更具体地说,我想修改 Alan 的解决方案,以便可以将射弹武器附加到手上,这基本上由三个关键值表示:武器原点(与手位置重叠)、射弹原点和射弹方向矢量。

下图应该可以更好地说明我所追求的:

澄清一下,绿色框表示 IK 链的当前端点,由鼠标光标控制。我正在寻找的是执行必要的偏移和/或旋转,以便武器枪口处的蓝色框代表鼠标光标的当前位置。如果控制/光标点在手臂 + 武器的半径之外,则 IK 系统应该偏移,以便伸出的武器的射弹矢量通过控制/光标点。

一些注意事项:

  • 武器和弹丸的相对角度是预先确定的,这意味着最终解决方案中唯一可修改的变量是肩角和肘角。
  • 理想的解决方案应该考虑到枪口方向(或武器本身)实际上可能平行于或不平行于肘部和手之间的线的可能性(例如:想象射弹从武器中射出的情况顶部而不是前面)。
  • 解决方案应尽可能优化,因为此代码将在可能有数十个演员的场景中运行每一帧)。

这是我当前的 C# (Unity) IK 代码,正如上面所暗示的,它在很大程度上基于 Alan 的教程:

void Start()
{
    length0 = Vector2.Distance(Joint0.position, Joint1.position);
    length1 = Vector2.Distance(Joint1.position, Hand.position);
}

void LateUpdate()
{
    length2 = Vector2.Distance(Joint0.position, Target.position);

    // Angle from Joint0 and Target
    diff = Target.position - Joint0.position;
    atan = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;

    // Is the target reachable?
    // If not, we stretch as far as possible
    if (length0 + length1 < length2)
    {
        jointAngle0 = atan;
        jointAngle1 = 0f;
    }
    else
    {
        cosAngle0 = ((length2 * length2) + (length0 * length0) - (length1 * length1)) / (2 * length2 * length0);
        cosAngle0 = Mathf.Clamp(cosAngle0, -1f, 1f);
        angle0 = Mathf.Acos(cosAngle0) * Mathf.Rad2Deg;

        cosAngle1 = ((length1 * length1) + (length0 * length0) - (length2 * length2)) / (2 * length1 * length0);
        cosAngle1 = Mathf.Clamp(cosAngle1, -1f, 1f);
        angle1 = Mathf.Acos(cosAngle1) * Mathf.Rad2Deg;

        if (FlipBendDirection)
        {
            angle0 *= -1;
            angle1 *= -1;
        }

        // So they work in Unity reference frame
        jointAngle0 = atan - angle0;
        jointAngle1 = 180f - angle1;
    }

    jointAngle0 += LimbAngleOffset;

    // Convert and clamp final angles from [-180, 180] to [0, 360], using a custom mod function to ensure proper handling of negative values
    jointAngle0 = CustomMathPackage.Mod(jointAngle0, 360f);
    jointAngle1 = CustomMathPackage.Mod(jointAngle1, 360f);

    euler0 = Joint0.transform.eulerAngles;
    euler0.z = jointAngle0;
    Joint0.transform.eulerAngles = euler0;

    euler1 = Joint1.transform.localEulerAngles;
    euler1.z = jointAngle1;
    Joint1.transform.localEulerAngles = euler1;
}

非常感谢任何帮助,无论有没有代码!另外,如果我的问题不是很清楚,请随时要求澄清。提前谢谢你!

c# unity3d trigonometry inverse-kinematics
© www.soinside.com 2019 - 2024. All rights reserved.