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; }