using UnityEngine;
using System;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
[RequireComponent(typeof(Animator))]
public class IKControl : MonoBehaviour
{
public InteractableItem[] lookObj = null;
public GameObject objToThrow;
public Text text;
public float weightDamping = 1.5f;
public float maxDistance = 10f;
public bool RightHandToTarget = true;
public float throwSpeed;
public bool handFinishedMove = false;
private List<InteractableItem> allDetectedItems;
private Animator animator;
private InteractableItem lastPrimaryTarget;
private float lerpEndDistance = 0.1f;
private float finalLookWeight = 0;
private bool transitionToNextTarget = false;
void Start()
{
animator = GetComponent<Animator>();
allDetectedItems = new List<InteractableItem>();
}
// Callback for calculating IK
void OnAnimatorIK()
{
if (lookObj != null)
{
InteractableItem primaryTarget = null;
float closestLookWeight = 0;
// Here we find the target which is closest (by angle) to the players view line
allDetectedItems.Clear();
foreach (InteractableItem target in lookObj)
{
Vector3 lookAt = target.transform.position - transform.position;
lookAt.y = 0f;
// Filter out all objects that are too far away
//if (lookAt.magnitude > maxDistance) continue;
if (lookAt.magnitude > target.distance) continue;
float dotProduct = Vector3.Dot(new Vector3(transform.forward.x, 0f, transform.forward.z).normalized, lookAt.normalized);
float lookWeight = Mathf.Clamp(dotProduct, 0f, 1f);
if (lookWeight > 0.1f && lookWeight > closestLookWeight)
{
closestLookWeight = lookWeight;
primaryTarget = target;
allDetectedItems.Add(target);
}
}
if (primaryTarget != null)
{
if ((lastPrimaryTarget != null) && (lastPrimaryTarget != primaryTarget) && (finalLookWeight > 0f))
{
// Here we start a new transition because the player looks already to a target but
// we have found another target the player should look at
transitionToNextTarget = true;
}
}
// The player is in a neutral look position but has found a new target
if ((primaryTarget != null) && !transitionToNextTarget)
{
if(primaryTarget.actionwithoutthrow == true)
{
RightHandToTarget = true;
}
lastPrimaryTarget = primaryTarget;
//finalLookWeight = Mathf.Lerp(finalLookWeight, closestLookWeight, Time.deltaTime * weightDamping);
finalLookWeight = Mathf.Lerp(finalLookWeight, 1f, Time.deltaTime * weightDamping);
float bodyWeight = finalLookWeight * .75f;
animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
animator.SetLookAtPosition(primaryTarget.transform.position);
if (RightHandToTarget && primaryTarget.interactableMode == InteractableItem.InteractableMode.Action
|| RightHandToTarget && primaryTarget.interactableMode == InteractableItem.InteractableMode.ActionWithoutThrow)
{
Vector3 relativePos = primaryTarget.transform.position - transform.position;
Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 1f * closestLookWeight);
animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);
// -> new code block
if (finalLookWeight > 0.95f) // here you can play with a value between 0.95f -> 1.0f
{
handFinishedMove = true;
if(primaryTarget.action == true && primaryTarget.interactableMode == InteractableItem.InteractableMode.Action)
// call your funtion to shoot something here
StartCoroutine(ThrowObject(objToThrow.transform, primaryTarget.transform.position, 30f));
}
}
}
// Let the player smoothly look away from the last target to the neutral look position
if ((primaryTarget == null && lastPrimaryTarget != null) || transitionToNextTarget)
{
finalLookWeight = Mathf.Lerp(finalLookWeight, 0f, Time.deltaTime * weightDamping);
float bodyWeight = finalLookWeight * .75f;
animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
animator.SetLookAtPosition(lastPrimaryTarget.transform.position);
if (RightHandToTarget)
{
Vector3 relativePos = lastPrimaryTarget.transform.position - transform.position;
Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.5f * closestLookWeight);
animator.SetIKPosition(AvatarIKGoal.RightHand, lastPrimaryTarget.transform.position);
}
if (finalLookWeight < lerpEndDistance)
{
transitionToNextTarget = false;
finalLookWeight = 0f;
lastPrimaryTarget = null;
}
}
// Show primary object found by the player
if (primaryTarget != null)
{
text.text = primaryTarget.description;
}
else
{
text.text = "";
}
}
}
IEnumerator ThrowObject(Transform objectToMove, Vector3 toPosition, float duration)
{
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
Vector3 currentPos = objectToMove.position;
float time = Vector3.Distance(currentPos, toPosition) / (duration - counter) * Time.deltaTime;
objectToMove.position = Vector3.MoveTowards(currentPos, toPosition, time);
yield return null;
}
}
}
I added a new flag name handFinishedMove and tried to use it in line 99 set it to true :
if (RightHandToTarget && primaryTarget.interactableMode == InteractableItem.InteractableMode.Action
|| RightHandToTarget && primaryTarget.interactableMode == InteractableItem.InteractableMode.ActionWithoutThrow)
{
Vector3 relativePos = primaryTarget.transform.position - transform.position;
Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 1f * closestLookWeight);
animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);
// -> new code block
if (finalLookWeight > 0.95f) // here you can play with a value between 0.95f -> 1.0f
{
handFinishedMove = true;
if(primaryTarget.action == true && primaryTarget.interactableMode == InteractableItem.InteractableMode.Action)
// call your funtion to shoot something here
StartCoroutine(ThrowObject(objToThrow.transform, primaryTarget.transform.position, 30f));
}
}
Then in another script : but handFinishedMove is never true.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UnlockCrate : MonoBehaviour
{
public GameObject carte;
public Animation anim;
public IKControl ikControl;
private bool playAnimOnce = false;
private void Update()
{
var distance = Vector3.Distance(carte.transform.position, transform.position);
if (distance < 1.5f)
{
if (!playAnimOnce)
{
if(ikControl.handFinishedMove == true)
{
anim.Play("Crate_Open");
}
playAnimOnce = true;
}
}
else if (playAnimOnce)
{
anim.Play("Crate_Close");
playAnimOnce = false;
}
}
}