Ejemplo n.º 1
0
    private void Update()
    {
        float velMag = _velocity.magnitude;

        GetLegsPlanted(out int numberOfLimbsPlanted, out float percentLimbsFromMinPlanted);

        #region update ik controller

        var data = new IKInterpData(transform, _yawAngle, _velocity, velMag, _minMaxVelocity);
        for (int i = 0; i < Limbs.Count; i++)
        {
            Limbs[i].ManualUpdate(data);
        }

        #region sort limbs by last used index
        //insertion sort from largest to smallest
        for (int i = 0; i < Limbs.Count; i++)
        {
            int currentMax      = -1;
            int currentMaxIndex = -1;

            for (int j = i; j < Limbs.Count; j++)
            {
                if (Limbs[j].LastRetargetAttemptIndex > currentMax)
                {
                    currentMax      = Limbs[j].LastRetargetAttemptIndex;
                    currentMaxIndex = j;
                }
            }

            var cache1 = Limbs[i];
            var cache2 = Limbs[currentMaxIndex];

            Limbs[i] = cache2;
            Limbs[currentMaxIndex] = cache1;
        }
        #endregion


        #region retargeting

        _timeBetweenLastSucessfulLegRetarget += Time.deltaTime;

        //if haven't too recently retargeted a leg...
        //find new target if ik wants new target
        if (_timeBetweenLastSucessfulLegRetarget > MinIntervalBetweenLegRetarget)


        #region retarget if a leg desires a retarget
        {
            for (int i = 0; i < Limbs.Count; i++)
            {
                if (numberOfLimbsPlanted < MinLegsOnGround) //if we need more legs to be planted, don't retarget planted legs
                {
                    if (Limbs[i].IKState.DesiresNewTarget && !Limbs[i].IKState.Planted)
                    {
                        if (SetNewTarget(Limbs[i]))
                        {
                            break;
                        }
                        else
                        {
                            Limbs[i].LastRetargetAttemptIndex = 0;
                        }
                    }
                }

                else if (Limbs[i].IKState.DesiresNewTarget)
                {
                    if (SetNewTarget(Limbs[i]))
                    {
                        break;
                    }
                }
            }
        }
        #endregion


        bool SetNewTarget(IKController limb)
        {
            bool newTargetFound = limb.SetTarget(_minMaxVelocity, Mathf.DeltaAngle(_yawAngle, _lastPhysicFramesYawAngle), _yawAngle, _velocity, velMag);

            for (int j = 0; j < Limbs.Count; j++)
            {
                Limbs[j].LastRetargetAttemptIndex++;
            }

            limb.LastRetargetAttemptIndex = 0;

            if (newTargetFound)
            {
                _timeBetweenLastSucessfulLegRetarget = 0;
            }

            return(newTargetFound);
        }

        #endregion
        #endregion
    }
Ejemplo n.º 2
0
    public void ManualUpdate(IKInterpData interpData)
    {
        SolveIKAndDetermineStates();
        InterpolateToTargetAndDetermineIfPlanted();
        InterpolateIncrement();

        //there are 3 basic states of operation: 1) no target data == interp to resting position 2) out of reach ik 3) and in reach leg ik
        void SolveIKAndDetermineStates()
        {
            if (TargetData == null)
            {
                for (int i = 0; i < Segments.Count; i++)
                {
                    Segments[i].ResetToResting();
                }
            }
            else
            {
                _ikState.DistToTarget = Vector3.Distance(Segments[0].transform.position, TargetData.Value.Hit.point);

                Vector3 goal = TargetData.Value.Hit.point;
                //Debug.DrawRay(legLeft, normal, Color.red, .1f);
                if (_ikState.DistToTarget < Reach)
                {
                    for (int i = Segments.Count - 1; i >= 0; i--)
                    {
                        Segments[i].ResetToResting();
                    }

                    for (int solverCount = 0; solverCount < _maxIKItterations; solverCount++)
                    {
                        for (int i = Segments.Count - 1; i >= 0; i--)
                        {
                            //todo use abs distance
                            var tipDistFromTarget = Vector3.Distance(Segments[Segments.Count - 1].IKTarget.SegmentEnd.position, TargetData.Value.Hit.point);
                            if (tipDistFromTarget < _distanceToleranceToTarget)
                            {
                                break;
                            }

                            var currentSeg = Segments[i];
                            currentSeg.IKItterateInReach(Segments[Segments.Count - 1].IKTarget.SegmentEnd.position, goal);
                        }
                    }
                }
                else
                {
                    for (int i = Segments.Count - 1; i >= 0; i--)
                    {
                        Segments[i].IKItterateInReach(Segments[Segments.Count - 1].IKTarget.SegmentEnd.position, goal);
                    }
                }

                #region does desire new target?
                if (Mathf.Abs(TargetData.Value.InitialYaw - interpData.BodyYaw) >= _maxYawChangeBeforeDesiresNewTarget)
                {
                    _ikState.DesiresNewTarget = true;
                    return;
                }

                var shoulderDistFromTarget = Vector3.Distance(Segments[0].transform.position, TargetData.Value.Hit.point); //todo use abs distance
                if (shoulderDistFromTarget > Reach)
                {
                    _ikState.DesiresNewTarget = true;
                    return;
                }

                if (IsPointWithinNoGoZones(Segments[Segments.Count - 1].IKTarget.SegmentEnd.position))
                {
                    _ikState.DesiresNewTarget = true;
                    return;
                }
                #endregion
            }
        }

        void InterpolateToTargetAndDetermineIfPlanted()
        {
            float interpProgress;

            if (TargetData.HasValue)
            {
                interpProgress = Mathf.Clamp01(_interpolationProgressRawCache / _totalTargetInterpTime);
                var tipDistFromTarget = Vector3.Distance(Segments[Segments.Count - 1].IKTarget.SegmentEnd.position, TargetData.Value.Hit.point);
                _ikState.Planted = tipDistFromTarget < _distanceToleranceToTarget;
            }
            else
            {
                _ikState.Planted = false;
                interpProgress   = Mathf.Clamp01(_interpolationProgressRawCache / _totalNoTargetInterpTime);
            }

            for (int i = 0; i < Segments.Count; i++)
            {
                Segments[i].InterpolateTowardsTarget(interpProgress);
            }
        }

        void InterpolateIncrement()
        {
            _interpolationProgressRawCache += Time.deltaTime;
            _ikState.TimeSinceNewTarget    += Time.deltaTime;
        }
    }