//TODO: make generating the timings somewhat automated public void ScheduleContact(bool rightHand, IKTiming[] timings, float duration) { IKSegment[] chain = (rightHand ? right : left); IKEndEffector eff = (rightHand ? RightEffector : LeftEffector); //just to be sure things are in the right order timings = timings.OrderBy(x => x.Timing).ToArray(); List<Quaternion[]> goals = new List<Quaternion[]>(); //calculate orientations for(int i = 0; i < timings.Length; i++) { Quaternion[] result; if (IKResolve.CCD(chain, eff, timings[i].Target, out result)) { goals.Add(result); } else { Debug.LogWarning("Unreachable goal"); return; } } UnityEngine.Assertions.Assert.IsTrue(goals.Count == timings.Length); //schedule StartCoroutine(ScheduleIK(chain, timings, goals, duration)); }
IEnumerator ScheduleIK(IKSegment[] chain, IKTiming[] timings, List<Quaternion[]> rotations, float duration) { float lastTiming = 0; for(int i = 0; i < timings.Length; i++) { float revert = 0f; float reach = (timings[i].Timing - lastTiming) * duration; if (i == timings.Length - 1) { revert = (1 - timings[i].Timing) * duration; } for (int seg = 0; seg < chain.Length; seg++) { chain[seg].SetTargetRotation(rotations[i][seg]); StartCoroutine(ScheduleIK(chain[seg], reach, 0, revert, 0)); } lastTiming = timings[i].Timing; yield return new WaitForSeconds(reach); if(timings[i].GrabTarget) { chain[chain.Length - 1].Grab(timings[i].Target); } } }