Пример #1
0
        private void Update()
        {
            _isMoving = false;

            if (_obstacle != null && _obstacle.enabled)
            {
                _obstacle.enabled = false;
            }

            if (_motor == null || !_motor.IsAlive)
            {
                if (_wasMoving)
                {
                    Message("OnStopMoving");
                    _wasMoving = false;
                }

                _mode = Mode.none;
                return;
            }

            if (_isCrouching)
            {
                _motor.InputCrouch();
            }

            if (_isAvoidingMover)
            {
                if (_avoidingTimer > float.Epsilon)
                {
                    _avoidingTimer -= Time.deltaTime;
                    move(_avoidDirection, 1, false);
                }
                else
                {
                    _isAvoidingMover = false;
                }
            }

            if (_mode == Mode.none)
            {
                if (_wasMoving)
                {
                    Message("OnStopMoving");
                    _wasMoving = false;
                }

                checkIncomingCollisions(Vector3.zero, 1);

                return;
            }

            if (DebugDestination)
            {
                Debug.DrawLine(transform.position, _target, Color.blue);
            }

            if (DebugPath)
            {
                for (int i = 0; i < _pathLength - 1; i++)
                {
                    if (i == _currentPathIndex)
                    {
                        Debug.DrawLine(_pathPoints[i], _pathPoints[i + 1], Color.cyan);
                        Debug.DrawLine(_pathPoints[i + 1], _pathPoints[i + 1] + Vector3.up, Color.cyan);
                    }
                    else
                    {
                        Debug.DrawLine(_pathPoints[i], _pathPoints[i + 1], Color.green);
                    }
                }
            }

            var vector = _target - transform.position;

            vector.y = 0;

            var direction = vector.normalized;
            var side      = Vector3.Cross(direction, Vector3.up);

            if (_futureCircleDirection == 0)
            {
                _circleWait = 0;
            }

            switch (_mode)
            {
            case Mode.inDirection:
                if (!checkIncomingCollisions(_direction, _speed))
                {
                    if (canMoveInDirection(_direction))
                    {
                        move(_direction, _speed, true);
                    }

                    _inDirectionLeft -= Time.deltaTime;

                    if (_inDirectionLeft <= float.Epsilon)
                    {
                        _mode = Mode.none;
                    }
                }
                break;

            case Mode.toPosition:
                var vectorToPath     = Vector3.zero;
                var isCloseToThePath = false;
                var distanceToPath   = 0f;

                if (_currentPathIndex <= _pathLength - 1)
                {
                    vectorToPath     = Util.VectorToSegment(transform.position, _pathPoints[_currentPathIndex], _pathPoints[_currentPathIndex + 1]);
                    distanceToPath   = vectorToPath.magnitude;
                    isCloseToThePath = distanceToPath < 0.5f;
                }

                if (!isCloseToThePath)
                {
                    updatePath();
                }

                var isLastStepOnPartialPath = _currentPathIndex >= _pathLength - 2 && _path.status == NavMeshPathStatus.PathPartial;

                if (_path.status != NavMeshPathStatus.PathInvalid && !_hasCheckedIfReachable)
                {
                    if (_pathLength == 0 || Vector3.Distance(_pathPoints[_pathLength - 1], _positionToCheckIfReachable) >= 0.2f)
                    {
                        Message("OnPositionUnreachable", _positionToCheckIfReachable);
                    }

                    _hasCheckedIfReachable = true;
                }

                if (vector.magnitude >= 0.3f && !isLastStepOnPartialPath)
                {
                    if (_path.status == NavMeshPathStatus.PathInvalid || _pathLength == 0)
                    {
                        updatePath();
                    }

                    var point = _currentPathIndex + 1 < _pathLength ? _pathPoints[_currentPathIndex + 1] : _target;

                    if (!AIUtil.IsPositionOnNavMesh(point))
                    {
                        updatePath();
                    }

                    direction   = point - transform.position;
                    direction.y = 0;

                    var distanceToPoint = direction.magnitude;

                    if (distanceToPoint > float.Epsilon)
                    {
                        direction /= distanceToPoint;
                    }

                    if (!checkIncomingCollisions(direction, _speed))
                    {
                        if (distanceToPoint < 0.2f && _currentPathIndex + 1 < _pathLength)
                        {
                            var index = _currentPathIndex;

                            if (distanceToPoint > 0.07f && _currentPathIndex + 2 < _pathLength)
                            {
                                if (Vector3.Dot(point - transform.position, _pathPoints[_currentPathIndex + 2] - transform.position) <= 0.1f)
                                {
                                    _currentPathIndex++;
                                }
                            }
                            else
                            {
                                _currentPathIndex++;
                            }
                        }

                        if (distanceToPath > 0.12f)
                        {
                            direction = (direction + vectorToPath).normalized;
                        }

                        if (Vector3.Dot(direction, _direction) < 0.9f)
                        {
                            updateDirection(direction, false);
                        }

                        move(direction, _speed, false);
                    }
                }
                else
                {
                    if (vector.magnitude > 0.03f)
                    {
                        if (!checkIncomingCollisions(direction, _speed))
                        {
                            if (vector.magnitude < 0.2f)
                            {
                                _motor.InputImmediateCoverSearch();
                                transform.position = Util.Lerp(transform.position, _target, 6);
                            }
                            else
                            {
                                if (_motor.IsInCover)
                                {
                                    move(direction, 1.0f, false);
                                }
                                else
                                {
                                    move(direction, 0.5f, false);
                                }
                            }
                        }
                    }
                    else
                    {
                        _motor.transform.position = _target;
                        _mode = Mode.none;
                    }
                }
                break;

            case Mode.fromPosition:
                _pathLength = 0;

                if (!checkIncomingCollisions(-direction, _speed))
                {
                    direction = -direction;

                    if (canMoveInDirection(direction))
                    {
                        _motor.InputMovement(new CharacterMovement(direction, 1.0f));
                        _isMoving = true;
                    }
                    else
                    {
                        if (_side == 0)
                        {
                            if (Random.Range(0, 10) < 5 && _motor.IsFreeToMove(side, 0.5f, 0.25f))
                            {
                                _side = 1;
                            }
                            else
                            {
                                _side = -1;
                            }
                        }

                        if (!canMoveInDirection(side * _side))
                        {
                            if (!_motor.IsFreeToMove(-side * _side, 0.5f, 0.25f))
                            {
                                Message("OnMoveFromFail");
                            }
                            else
                            {
                                _side = -_side;
                            }
                        }

                        move(side * _side, 1.0f, true);
                    }

                    updateDirection(direction, false);

                    if (_isRunningAwayTemp)
                    {
                        _runningAwayFramesLeft--;

                        if (_runningAwayFramesLeft <= 0)
                        {
                            ToStopMoving();
                        }
                    }
                }

                break;

            case Mode.circle:
                _pathLength = 0;

                if (_futureCircleDirection != 0)
                {
                    if (_circleWait > float.Epsilon)
                    {
                        _circleWait -= Time.deltaTime;
                    }

                    if (_circleWait < float.Epsilon)
                    {
                        _circleWait            = 0;
                        _side                  = _futureCircleDirection;
                        _futureCircleDirection = 0;
                    }
                }


                if (_futureCircleDirection == 0)
                {
                    if (_side == 0)
                    {
                        if (Random.Range(0, 10) < 5 && canMoveInDirection(side))
                        {
                            _side = 1;
                        }
                        else
                        {
                            _side = -1;
                        }
                    }

                    if (!canMoveInDirection(side * _side))
                    {
                        if (!canMoveInDirection(-side * _side))
                        {
                            Message("OnCircleFail");
                        }
                        else
                        {
                            _futureCircleDirection = -_side;
                            _circleWait            = CircleDelay;
                        }
                    }

                    direction = side * _side;

                    if (!checkIncomingCollisions(direction, _speed))
                    {
                        move(direction, 1.0f, true);
                        updateDirection(direction, false);
                    }
                }
                break;
            }

            if (_isMoving && !_wasMoving)
            {
                Message("OnMoving");
            }
            else if (!_isMoving && _wasMoving)
            {
                Message("OnStopMoving");
            }

            _wasMoving = _isMoving;
        }