使用 IK 时武器不符合目标位置

Weapon does't meet the target position when using IK

我写了下面的代码,当他停止射击时,枪会移动到他的肩膀位置,它确实有效……但只有一次。在那之后,它开始不符合目标,即使它的坐标保持不变。我已经用 LerpSmoothDampMoveTowards 试过了……还是不明白问题出在哪里。 P.S。完美射击时枪会移动到肩膀,当角色停止射击并试图回到空闲姿势时,它会开始发生。

编辑:事实证明旋转也有问题......或者可能只是旋转。我什至不知道这一点。

正在发生的事情的视频:https://youtu.be/CheQiomYtm8

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnitControl;

public class BlastIKController : MonoBehaviour
{
    public WeaponState wpState;
    public GameObject weapon;
    public GameObject RightShoulder;
    public GameObject HumanSpine;
    public GameObject WeaponSpawn;
    public LayerMask lmask;
    public BlastIKHandler ikHandle;
    public Material targetMat;
    public Material defMat;
    public GameObject target;

    public GameObject WeaponIdle;
    public bool isShooting = false;
    //public bool InIdle = true;

    LineRenderer ShootLine;

    public GameObject WeaponInstance;

    Animator anim;

    public float speedMove;
    public float speedRot;

    // Use this for initialization
    void Awake()
    {
        GameObject weaponInst = Instantiate(weapon, WeaponSpawn.transform);
        WeaponInstance = weaponInst;
        WeaponInstance.transform.localPosition = new Vector3(0, 0, 0);
        wpState = weaponInst.GetComponent<WeaponState>();
        ikHandle = this.GetComponent<BlastIKHandler>();
        ShootLine = this.GetComponent<LineRenderer>();
        anim = this.GetComponent<Animator>();
        ikHandle.RightShoulder = RightShoulder;
        ikHandle.leftHandTarget = wpState.leftHandIdle.transform;
        ikHandle.rightHandTarget = wpState.rightHandTarget.transform;

        //Позиция оружия
        wpState.shoulder.transform.position = ikHandle.WeaponIdlePos.position;
        wpState.shoulder.transform.rotation = ikHandle.WeaponIdlePos.rotation;
    }

    // Update is called once per frame
    void Update()
    {
        RaycastHit hit;

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        #region SearchTarget
        if (Physics.Raycast(ray, out hit, Mathf.Infinity, lmask))
        {
            if (hit.collider.gameObject.tag == "Target")
            {
                ShootLine.positionCount = 2;
                ShootLine.SetPosition(0, HumanSpine.transform.position);
                ShootLine.SetPosition(1, hit.collider.gameObject.transform.position);

                if (Input.GetMouseButton(0))
                {
                    if (target == null)
                    {
                        target = hit.collider.gameObject;
                        MeshRenderer ms = hit.collider.gameObject.GetComponent<MeshRenderer>();
                        ms.material = targetMat;
                        ikHandle.targetPos = hit.collider.gameObject;
                    }
                    else
                    {
                        MeshRenderer ms = target.GetComponent<MeshRenderer>();
                        ms.material = defMat;
                        target = hit.collider.gameObject;
                        ms = target.GetComponent<MeshRenderer>();
                        ms.material = targetMat;
                        ikHandle.targetPos = hit.collider.gameObject;
                    }
                }
            }
        }
        #endregion

        #region Shooting
        Shooting();

        if (isShooting)
        {
            if (target != null)
            {
                bool isShoot = anim.GetBool("Shoot");
                if (!isShoot)
                {
                    StartCoroutine(MoveToShoot(RightShoulder.transform.position));
                    ikHandle.leftHandTarget = wpState.leftHandTarget.transform;
                    anim.SetBool("Shoot", true);
                    //InIdle = false;
                }
            }
        }
        else
        {
           // float stepMove = speedMove * Time.deltaTime;
           // wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
           // //if (!InIdle)
           // //{
           //     //    StartCoroutine(MoveToIdle(ikHandle.WeaponIdlePos.position));

           //// }
           // //InIdle = true;
           // //float stepMove = speedMove * Time.deltaTime;
           // //while (wpState.shoulder.transform.position != ikHandle.WeaponIdlePos.position)
           // //{
           // //    wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
           // //}
           // ////wpState.shoulder.transform.position = ikHandle.WeaponIdlePos.position;
           // ////wpState.shoulder.transform.position = Vector3.MoveTowards(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
           // float stepRot = speedRot * Time.deltaTime;
           // //while (wpState.shoulder.transform.rotation != ikHandle.WeaponIdlePos.rotation)
           // //{
           //     wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, ikHandle.WeaponIdlePos.rotation, stepRot);
           // //}
           // ////wpState.shoulder.transform.rotation = ikHandle.WeaponIdlePos.rotation;
           // ikHandle.leftHandTarget = wpState.leftHandIdle.transform;
           // anim.SetBool("Shoot", false);          
        }
        #endregion
    }

    void LateUpdate()
    {
        if (!isShooting)
        {
            float stepMove = speedMove * Time.deltaTime;
            stepMove += Time.deltaTime / speedMove;
            Vector3 velocity = Vector3.zero;
            //.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
            wpState.shoulder.transform.position = Vector3.MoveTowards(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
            //wpState.shoulder.transform.position = Vector3.SmoothDamp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, ref velocity, stepMove);
           // wpState.shoulder.transform.position = Vector3.SmoothDamp()

            float stepRot = speedRot * Time.deltaTime;
            wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, ikHandle.WeaponIdlePos.rotation, stepRot);

            ikHandle.leftHandTarget = wpState.leftHandIdle.transform;
            anim.SetBool("Shoot", false);
        }
    }

    void Shooting()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            isShooting = !isShooting;
        }
    }

    IEnumerator MoveToShoot(Vector3 WPposition)
    {
        float step = speedMove * Time.deltaTime;
        while (wpState.shoulder.transform.position != WPposition)
        {
            wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, WPposition, step);
            Vector3 relativeWeaponPos = ikHandle.targetPos.transform.position - wpState.shoulder.transform.position;
            Quaternion WeaponRotation = Quaternion.LookRotation(relativeWeaponPos);
            wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, WeaponRotation, step);
            yield return null;
        }
    }

    IEnumerator MoveToIdle(Vector3 WPposition)
    {
        float stepMove = speedMove * Time.deltaTime;
        float stepRot = speedRot * Time.deltaTime;
        while (wpState.shoulder.transform.position != WPposition)
        {
            wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, WPposition, stepMove);
            wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, ikHandle.WeaponIdlePos.transform.rotation, stepRot);
            yield return null;
        }           
        wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
    }
}

原来是这样。原来协程在Update搞混了,他们同时工作

所以...我从代码中删除了所有协程,然后在更新中使用 Lerp 和 sLerp 移动和旋转。

不过有一件事,我还必须添加一个检查以确保两个位置都满足,然后才开始拍摄。

P.S。如果你愿意,我可以添加我稍后更改的代码。