Beispiel #1
0
        IEnumerator <float> MoveAlongPath(BaseUnit unit, ABPath path, float speed)
        {
            if (path.error || path.vectorPath.Count == 0)
            {
                throw new ArgumentException("Cannot follow an empty path");
            }

            PreMoveUnit = unit;
            Callback_OnMoveStart?.Invoke(unit);

            // Very simple movement, just interpolate using a catmull rom spline
            float distanceAlongSegment = 0;

            for (int i = 0; i < path.vectorPath.Count - 1; i++)
            {
                var p0 = path.vectorPath[Mathf.Max(i - 1, 0)];
                // Start of current segment
                var p1 = path.vectorPath[i];
                // End of current segment
                var p2 = path.vectorPath[i + 1];
                var p3 = path.vectorPath[Mathf.Min(i + 2, path.vectorPath.Count - 1)];

                var segmentLength = Vector3.Distance(p1, p2);

                while (distanceAlongSegment < segmentLength)
                {
                    var interpolatedPoint = MathUtil.CatmullRom(p0, p1, p2, p3, distanceAlongSegment / segmentLength);

                    var targetRot = Quaternion.LookRotation((p2 - p1).SetY(0), Vector3.up);
                    unit.Rot = Quaternion.Slerp(unit.Rot, targetRot, Time.deltaTime * 10);

                    unit.transform.position = interpolatedPoint;

                    Callback_OnMovingAlone?.Invoke(unit, p0, p1, p2, p3);
                    yield return(Timing.WaitForOneFrame);

                    distanceAlongSegment += Time.deltaTime * speed;
                }

                distanceAlongSegment -= segmentLength;
            }

            Vector3 target = path.vectorPath[path.vectorPath.Count - 1];

            unit.Pos = target;
            Callback_OnMoveEnd?.Invoke(unit);
        }
Beispiel #2
0
        protected override IEnumerator <float> OnFollowPathCoroutine()
        {
            IsMovingFlag = false;
            //是否为第一段移动
            bool isFirstMoved = false;
            //当前已经走过的路段
            float distanceAlongSegment = 0;
            //当前路段长度
            var segmentLength = 0.0f;
            //节点的大小
            float nodeSize = AStarMgr.Ins.data.gridGraph.nodeSize;
            //最大可以移动的距离
            float maxMoveDistance = nodeSize * MaxMovePoint;
            //已经移动的距离
            float movedDistance = 0;
            var   moveStep      = Time.smoothDeltaTime * RealMoveSpeed;

            IsForceBreak   = false;
            IsFinalPosMove = false;
            for (int i = 0; i < ABPath.vectorPath.Count - 1; i++)
            {
                CurIndex = i;
                var p1 = ABPath.vectorPath[i];
                var p2 = ABPath.vectorPath[i + 1];
                segmentLength = Vector3.Distance(p1, p2);
                if (CurMovePoint <= segmentLength)
                {
                    p2 = (Vector3)AStarMgr.GetSafeNode(p2).position;;
                }
                while (IsHaveMoveSegment() && !IsForceBreak)
                {
                    if (CurMovePoint < nodeSize &&
                        MathUtil.Approximately(SelfBaseUnit.Pos, p2))
                    {
                        IsForceBreak = true;
                    }
                    else
                    {
                        LerpMove(p1, p2, 1, true, false);
                    }

                    yield return(Timing.WaitForOneFrame);

                    if (!isFirstMoved)
                    {
                        isFirstMoved = true;
                        Callback_OnFirstMovingAlone?.Invoke();
                    }
                }

                distanceAlongSegment -= segmentLength;
                OnMoveStep(movedDistance, maxMoveDistance, nodeSize, segmentLength);
                CurIndex++;
                if (!IsCanMove || IsForceBreak)
                {
                    break;
                }
            }

            //计算最后的安全落点
            yield return(Timing.WaitUntilDone(FinalPosMove()));

            if (CurMovePoint < 1)
            {
                CurMovePoint = 0;
            }
            IsMovingFlag = true;
            Callback_OnMoveDestination?.Invoke();
            StopPath();

            //最后位置点的矫正
            IEnumerator <float> FinalPosMove()
            {
                IsFinalPosMove = true;
                Vector3 startPos = SelfBaseUnit.Pos;
                var     finalPos = GetFinalPos(startPos);

                if (MathUtil.Approximately(startPos, finalPos))
                {
                    yield break;
                }
                //将单位移动到最终的目标节点
                distanceAlongSegment = 0;
                segmentLength        = Vector3.Distance(startPos, finalPos);
                while (IsHaveMoveSegment())
                {
                    LerpMove(startPos, finalPos, 1, segmentLength > nodeSize, true);
                    yield return(Timing.WaitForOneFrame);
                }
                SelfBaseUnit.Pos = finalPos;

                //如果目标无效,进入递归
                if (!MathUtil.Approximately(finalPos, GetFinalPos(SelfBaseUnit.Pos)))
                {
                    yield return(Timing.WaitUntilDone(FinalPosMove()));
                }
                IsForceBreak   = false;
                IsFinalPosMove = false;
            }

            bool LerpMove(Vector3 p1, Vector3 p2, float speedMul = 1.0f, bool isRot = true, bool isFinalCorrect = false)
            {
                float aiSpeedMul = 1;

                if (BaseGlobal.FOWMgr != null &&
                    BaseGlobal.FOWMgr.IsInFog(p2) &&
                    SelfBaseUnit != null &&
                    SelfBaseUnit.IsAI() &&
                    SelfBaseUnit.FOWMgr != null &&
                    !SelfBaseUnit.FOWMgr.IsVisible &&
                    !SelfBaseUnit.FOWMgr.IsPreVisible)
                {
                    aiSpeedMul = 10;
                }
                if (!isFinalCorrect && IsForceBreak)
                {
                    return(false);
                }
                var tempMoveStep      = moveStep * speedMul * aiSpeedMul;
                var interpolatedPoint = Vector3.Lerp(p1, p2, distanceAlongSegment / segmentLength);
                var targetRot         = Quaternion.LookRotation((p2 - p1).SetY(0), Vector3.up);

                if (isRot)
                {
                    SelfBaseUnit.Rot = Quaternion.Slerp(SelfBaseUnit.Rot, targetRot, tempMoveStep);
                }
                bool isValid = OnPreLerpMoveAlone(interpolatedPoint, tempMoveStep, movedDistance, maxMoveDistance, nodeSize, segmentLength, isFinalCorrect);

                if (!isValid)
                {
                    return(false);
                }
                SelfBaseUnit.Pos      = interpolatedPoint;
                movedDistance        += tempMoveStep;
                distanceAlongSegment += tempMoveStep;
                OnLerpMoveAlone(tempMoveStep, movedDistance, maxMoveDistance, nodeSize, segmentLength, isFinalCorrect);
                Callback_OnMovingAlone?.Invoke();
                return(true);
            }

            //是否有移动的路段
            bool IsHaveMoveSegment()
            {
                return(distanceAlongSegment < segmentLength);
            }
        }