unity-game-engineinverse-kinematics

Weapon does't meet the target position when using IK


I've written the following code making the gun move to the guy's shoulder position when he stops shooting and it does work...BUT ONLY ONCE. After that, it starts not to meet the target even though it's coordinates remain the same. I've tried it with Lerp, SmoothDamp, MoveTowards...still don't get where the problem lies. P.S. The gun moves to the shoulder when shooting perfectly, it starts happening when the character stops shooting and tries to go back to the Idle pose.

EDIT: Turns out there's also something wrong with rotation...or maybe it's just rotation. I don't even know at this point.

THE VIDEO of what's going on: https://youtu.be/CheQiomYtm8

THE CODE:

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);
    }
}

Solution

  • So, it was the following. It turns out that the coroutines got mixed up in Update and they worked at the same time.

    So...I removed all coroutines from the code and then moved and rotated using Lerp and sLerp in the update.

    There's one thing though, I also had to add a check for both bositions to meet, and after that it starts shooting and only then.

    P.S. I can add the code I changed later if you like.