Search Unity

Resolved How can I make the look at to be smoother slowly when using IK?

Discussion in 'Animation' started by JhonRA77, Oct 3, 2021.

  1. JhonRA77

    JhonRA77

    Joined:
    Sep 9, 2021
    Posts:
    51
    The script is very long so I will zoom in the specific script places of the problem and in the end I will add the full script too.

    The problem is at lines 209 - 235 when the player is smoothly looking away from the last target back to the natural look. The problem is that it's not that smooth.

    Code (csharp):
    1.  
    2. // Let the player smoothly look away from the last target to the neutral look position
    3.        if ((primaryTarget == null && lastPrimaryTarget != null) || transitionToNextTarget)
    4.        {
    5.            finalLookWeight = Mathf.Lerp(finalLookWeight, 0f, t / duration);//Time.deltaTime * weightDamping);
    6.            t += Time.deltaTime;
    7.  
    8.            float bodyWeight = finalLookWeight * .75f;
    9.            animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
    10.            animator.SetLookAtPosition(lastPrimaryTarget.transform.position);
    11.  
    12.            if (RightHandToTarget)
    13.            {
    14.                Vector3 relativePos = lastPrimaryTarget.transform.position - transform.position;
    15.                Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
    16.                animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
    17.                animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
    18.                animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.5f * closestLookWeight);
    19.                animator.SetIKPosition(AvatarIKGoal.RightHand, lastPrimaryTarget.transform.position);
    20.            }
    21.            
    22.            if (finalLookWeight < lerpEndDistance)
    23.            {
    24.                transitionToNextTarget = false;
    25.                finalLookWeight = 0f;
    26.                lastPrimaryTarget = null;
    27.                transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y, 0);
    28.            }
    29.        }
    30.  
    I changed the lines 211 and 212 it was before using only Time.deltaTime * weightDamping but I changed it to use the t variable and duration. duration is public.

    This part is working smooth slowly depending on the duration but it's not solving the problem.

    The problem is when the player is start looking away back to natural he is doing it at once almost at once like "jumping" to natural look.

    The lerp is helping for the last part when the player head is looking away to natural but not the part from looking the target item. I tried to set in other script the target to be null or the distance to 0 but nothing make it smooth slowly.

    I recorded a very short 13 seconds video clip of the problem. The problem is at second 5 to 7.



    The complete script :

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System;
    4. using System.Collections;
    5. using UnityEngine.UI;
    6. using System.Collections.Generic;
    7. using System.Linq;
    8. using TMPro;
    9.  
    10. [RequireComponent(typeof(Animator))]
    11. public class IKControl : MonoBehaviour
    12. {
    13.    public List<InteractableItem> lookObjs = new List<InteractableItem>();
    14.    public TextMeshProUGUI text;
    15.    public float weightDamping = 1.5f;
    16.    public bool RightHandToTarget = true;
    17.    public float throwSpeed;
    18.    public bool handFinishedMove = false;
    19.    public GameObject descriptionTextImage;
    20.    public GameObject naviParent;
    21.    public DimLights dimLights;
    22.    public Light[] naviLights;
    23.    public bool startMovingNAVI = false;
    24.    public InteractableItem target;
    25.    public bool toTarget = false;
    26.    public bool hasSent = false;
    27.    public InteractableItem leftHand;
    28.    public bool useHead = false;
    29.    public float duration;
    30.  
    31.    private List<InteractableItem> allDetectedItems;
    32.    private Animator animator;
    33.    private InteractableItem lastPrimaryTarget;
    34.    private float lerpEndDistance = 0.1f;
    35.    private float finalLookWeight = 0;
    36.    private bool transitionToNextTarget = false;
    37.    private List<string> objectsNames = new List<string>();
    38.    private bool setNaviRotation = false;
    39.    private float t;
    40.  
    41.    private void Awake()
    42.    {
    43.  
    44.    }
    45.  
    46.    void Start()
    47.    {
    48.        animator = GetComponent<Animator>();
    49.        allDetectedItems = new List<InteractableItem>();
    50.  
    51.        if (dimLights != null)
    52.        {
    53.            dimLights.lightsToDim = naviLights;
    54.        }
    55.  
    56.        t = 0;
    57.    }
    58.  
    59.    // Callback for calculating IK
    60.    void OnAnimatorIK()
    61.    {
    62.        if (lookObjs != null)
    63.        {
    64.            lookObjs.RemoveAll(x => x == null);
    65.  
    66.            InteractableItem primaryTarget = null;
    67.  
    68.            float closestLookWeight = 0;
    69.  
    70.            // Here we find the target which is closest (by angle) to the players view line
    71.            allDetectedItems.Clear();
    72.            foreach (InteractableItem target in lookObjs)
    73.            {
    74.                if(target.enabledInteraction == false)
    75.                {
    76.                    continue;
    77.                }
    78.  
    79.                Vector3 lookAt = target.transform.position - transform.position;
    80.                lookAt.y = 0f;
    81.  
    82.                // Filter out all objects that are too far away
    83.                if (lookAt.magnitude > target.distance) continue;
    84.  
    85.                float dotProduct = Vector3.Dot(new Vector3(transform.forward.x, 0f, transform.forward.z).normalized, lookAt.normalized);
    86.                float lookWeight = Mathf.Clamp(dotProduct, 0f, 1f);
    87.                if (lookWeight > 0.1f && lookWeight > closestLookWeight)
    88.                {
    89.                    closestLookWeight = lookWeight;
    90.                    primaryTarget = target;
    91.                }
    92.  
    93.                allDetectedItems.Add(target);
    94.            }
    95.  
    96.            if (allDetectedItems.Count == 2)
    97.            {
    98.                objectsNames = allDetectedItems.Select(item => item.transform.name).ToList();
    99.                if (objectsNames.Contains("NAVI") && objectsNames.Contains("Security Keypad Interactable"))
    100.                {
    101.                    InteractableItem navi = allDetectedItems.Single(item => item.transform.name == "NAVI");
    102.                    InteractableItem securitykeypad = allDetectedItems.Single(item => item.transform.name == "Security Keypad Interactable");
    103.                    var crate = GameObject.Find("Crate_0_0");
    104.  
    105.                    if (crate.gameObject.GetComponent<UnlockCrate>().HasOpened())
    106.                    {
    107.                        primaryTarget = navi;
    108.                        target = primaryTarget;
    109.                        startMovingNAVI = true;
    110.                    }
    111.                    else
    112.                    {
    113.                        primaryTarget = securitykeypad;
    114.                    }
    115.                }
    116.            }
    117.  
    118.            InteractWithTarget(primaryTarget, closestLookWeight);
    119.  
    120.            /*if (allDetectedItems.Count == 1)
    121.            {
    122.                var crate = GameObject.Find("Crate_0_0");
    123.                InteractableItem navi = allDetectedItems.Single(item => item.transform.name == "NAVI");
    124.  
    125.                if (crate.gameObject.GetComponent<UnlockCrate>().HasOpened())
    126.                {
    127.                    primaryTarget = navi;
    128.                    target = primaryTarget;
    129.                }
    130.            }
    131.  
    132.                */
    133.        }
    134.    }
    135.  
    136.    private void InteractWithTarget(InteractableItem primaryTarget, float closestLookWeight)
    137.    {
    138.        if (primaryTarget != null)
    139.        {
    140.            if ((lastPrimaryTarget != null) && (lastPrimaryTarget != primaryTarget) && (finalLookWeight > 0f))
    141.            {
    142.                // Here we start a new transition because the player looks already to a target but
    143.                // we have found another target the player should look at
    144.                transitionToNextTarget = true;
    145.            }
    146.        }
    147.  
    148.        // The player is in a neutral look position but has found a new target
    149.        if ((primaryTarget != null) && !transitionToNextTarget)
    150.        {
    151.            if (primaryTarget.IsAnyAction())//.interactableMode == InteractableItem.InteractableMode.ActionWithoutThrow)
    152.            {
    153.                RightHandToTarget = true;
    154.            }
    155.  
    156.            lastPrimaryTarget = primaryTarget;
    157.            //finalLookWeight = Mathf.Lerp(finalLookWeight, closestLookWeight, Time.deltaTime * weightDamping);
    158.            finalLookWeight = Mathf.Lerp(finalLookWeight, 1f, Time.deltaTime * weightDamping);
    159.            float bodyWeight = finalLookWeight * .1f;
    160.            animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
    161.            animator.SetLookAtPosition(primaryTarget.transform.position);
    162.  
    163.            if (RightHandToTarget && primaryTarget.IsAnyAction())
    164.            {
    165.                Vector3 relativePos = primaryTarget.transform.position - transform.position;
    166.                Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
    167.  
    168.                if (primaryTarget.interactableMode == InteractableItem.InteractableMode.ActionWithoutThrow)
    169.                {
    170.                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
    171.                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
    172.                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 1f * closestLookWeight);
    173.                    animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);
    174.                }
    175.  
    176.                if (primaryTarget.interactableMode == InteractableItem.InteractableMode.Action)
    177.                {
    178.                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
    179.                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
    180.                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.1f * closestLookWeight);
    181.                    animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);
    182.                }
    183.  
    184.                // -> new code block
    185.                if (finalLookWeight > 0.95f) // here you can play with a value between 0.95f -> 1.0f
    186.                {
    187.                    if (primaryTarget.interactableMode == InteractableItem.InteractableMode.Action
    188.                        && hasSent == false)
    189.                    {
    190.                        target = primaryTarget;
    191.                        toTarget = true;
    192.                        hasSent = true;
    193.                        primaryTarget.description = "";
    194.                        // Here I need to find where to make hasSent false again.
    195.                    }
    196.                }
    197.                else
    198.                {
    199.                    hasSent = false;
    200.                }
    201.  
    202.                if (finalLookWeight > 0.9f)
    203.                {
    204.                    handFinishedMove = true;
    205.                }
    206.            }
    207.        }
    208.  
    209.        // Let the player smoothly look away from the last target to the neutral look position
    210.        if ((primaryTarget == null && lastPrimaryTarget != null) || transitionToNextTarget)
    211.        {
    212.            finalLookWeight = Mathf.Lerp(finalLookWeight, 0f, t / duration);//Time.deltaTime * weightDamping);
    213.            t += Time.deltaTime;
    214.  
    215.            float bodyWeight = finalLookWeight * .75f;
    216.            animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
    217.            animator.SetLookAtPosition(lastPrimaryTarget.transform.position);
    218.  
    219.            if (RightHandToTarget)
    220.            {
    221.                Vector3 relativePos = lastPrimaryTarget.transform.position - transform.position;
    222.                Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
    223.                animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
    224.                animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
    225.                animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.5f * closestLookWeight);
    226.                animator.SetIKPosition(AvatarIKGoal.RightHand, lastPrimaryTarget.transform.position);
    227.            }
    228.            
    229.            if (finalLookWeight < lerpEndDistance)
    230.            {
    231.                transitionToNextTarget = false;
    232.                finalLookWeight = 0f;
    233.                lastPrimaryTarget = null;
    234.                transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y, 0);
    235.            }
    236.        }
    237.  
    238.        if (text != null)
    239.        {
    240.            // Show primary object found by the player
    241.            if (primaryTarget != null)
    242.            {
    243.                if (primaryTarget.description != "")
    244.                {
    245.                    descriptionTextImage.SetActive(true);
    246.                    text.text = primaryTarget.description;
    247.                }
    248.            }
    249.            else
    250.            {
    251.                text.text = "";
    252.                descriptionTextImage.SetActive(false);
    253.            }
    254.        }
    255.    }
    256.  
    257.    private void Update()
    258.    {
    259.        if (MenuController.LoadSceneForSavedGame == true && setNaviRotation == false)
    260.        {
    261.            transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y, 0);
    262.            setNaviRotation = true;
    263.        }
    264.    }
    265. }
    266.  
     
unityunity