Example #1
0
    private void Update()
    {
        //получаем вектор управления
        Vector2 moveControl = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));

        //определение ускорения и целевой линейной скорости
        float acceleration, goalValue = 0;

        if (moveControl.y == 0)
        {
            acceleration = _sleepDeceleration * Time.deltaTime;
        }
        else
        {
            acceleration = _acceleration * Time.deltaTime;
            goalValue    = moveControl.y * _maxSpeed;
        }
        //корректировка линейной скорости
        CurrSpeed = Mathf.MoveTowards(CurrSpeed, goalValue, acceleration);

        //определение ускорения и угловой скорости
        acceleration = _rotateSpeedAcceleration * Time.deltaTime;
        if (moveControl.x == 0)
        {
            goalValue = 0;
        }
        else
        {
            goalValue = _angularSpeed * moveControl.x;
        }
        //корректировка угловой скорости, не зависящей от линейной скорости
        _currRotateSpeed = Mathf.MoveTowards(_currRotateSpeed, goalValue, acceleration);
        //определение степени влияния лиейной скорости на конечную угловую скорость
        float rotateRate = Mathf.Clamp01(Mathf.Abs(CurrSpeed) / _angularSpeed);

        CurrRotateSpeed = rotateRate * _currRotateSpeed;

        if (_debug)
        {
            for (float forecastTime = Time.deltaTime; forecastTime < 5; forecastTime += Time.deltaTime)
            {
                Quaternion forecastRotation;
                Vector3    forecastPosition = AngularMath.Forecast(
                    transform.position,
                    transform.forward * CurrSpeed,
                    CurrRotateSpeed,
                    forecastTime,
                    out forecastRotation
                    );
                Debug.DrawRay(forecastPosition, Vector3.up, Color.green, 5);
            }
        }

        //применение линейной и угловой скоростей
        transform.position += transform.forward * CurrSpeed * Time.deltaTime;
        transform.Rotate(Vector3.up, CurrRotateSpeed * Time.deltaTime);
    }
Example #2
0
    //прогноз позиции корабя на время, которое нужно, чтобы до него долететь
    private Vector3 ForecastCarrierPosition(out float forecastTimeSec)
    {
        CarrierDispatch carrier = flight.carrier;

        //время, чтобы прилететь к кораблю
        forecastTimeSec = ToCarrierTime();

        Quaternion forecastRotation;
        //находим саму прогнозируемую позицию
        Vector3 carrierForecastPosition = AngularMath.Forecast(
            carrier.Position,
            carrier.Direction * carrier.LinearSpeed,
            carrier.AngularSpeed,
            forecastTimeSec,
            out forecastRotation
            );

        return(carrierForecastPosition);
    }
Example #3
0
    //находит точку захода посадку
    //чем более "правильное" положение занимает самолет относительно корабля, тем точка ближе к месту посадки,
    //"доводя" таким образом самолет до нужного направления захода на палубу
    private Vector3 GetStartLandingPoint()
    {
        CarrierDispatch carrier = flight.carrier;

        //сначала рассчитываем время прогноза позиции корабля
        float toCarrierDistance       = Vector3.Distance(Position, carrier.Position);
        float toCarrierTime           = toCarrierDistance / _minSpeed;
        float toCarrierDirectionAngle = Vector3.Angle(carrier.Direction, Direction);
        float toCarrierDirectionTime  = toCarrierDirectionAngle / _angularSpeed;
        float forecastTime            = toCarrierTime + toCarrierDirectionTime;
        //на основе времени прогноза расчитываем направление и позуцию корабля
        Quaternion forecastRotation;
        Vector3    forecastCarrierPosition = AngularMath.Forecast(
            carrier.Position,
            carrier.Direction * -Mathf.Abs(carrier.LinearSpeed),
            carrier.AngularSpeed,
            forecastTime,
            out forecastRotation
            );

        //расчитываем величину доворота курса до прогнозируемой позиции корабля до прогнозируемого направления корабля,
        Vector3 forecastCarrierDirection  = forecastRotation * carrier.Direction;
        Vector3 toForecastCarrierPosition = forecastCarrierPosition - Position;
        //это даст понимание расположения самолета относительно корабля в его прогнозируемой позиции
        Vector3 fromToCarrierToForecastDirectionEuler =
            Quaternion.FromToRotation(toForecastCarrierPosition, forecastCarrierDirection).eulerAngles -
            new Vector3(0, 180, 0);

        //на основе предыдущего расчета, определяем, в какую сторону должен будет поворачивать самолет
        float signedAngSpeed = _angularSpeed;

        if (fromToCarrierToForecastDirectionEuler.y > 0)
        {
            signedAngSpeed = -signedAngSpeed;
        }
        //коррекция угловой скорости самолета на угловую скорость корабля
        if (carrier.LinearSpeed > 0)
        {
            signedAngSpeed += Mathf.Max(carrier.AngularSpeed, 0);
        }
        else if (carrier.LinearSpeed < 0)
        {
            signedAngSpeed -= Mathf.Min(carrier.AngularSpeed, 0);
        }

        float maneurRadius;
        //расчет центра маневра от прогнозирумых позиции и нарпавления корабля
        Vector3 maneurCenter = AngularMath.CircleCenter(
            forecastCarrierPosition,
            forecastCarrierDirection * LinearSpeed,
            signedAngSpeed,
            out maneurRadius
            );

        if (_debug)
        {
            Vector3    radius = Vector3.forward * maneurRadius;
            Quaternion oneGeg = Quaternion.AngleAxis(1, Vector3.up);
            for (int i = 0; i < 360; i++)
            {
                Vector3 debugPoint = maneurCenter + radius;
                Debug.DrawRay(debugPoint, Vector3.up, Color.white);
                radius = oneGeg * radius;
            }
        }

        //строим гопотенузу прямого треугольника для расчета касательной
        Vector3 toManeurCenter = maneurCenter - Position;
        //расчет длины касатльной от позиции самолета к траектории виража на посадку
        float distanceToTangentPoint = Mathf.Pow(toManeurCenter.magnitude, 2) - Mathf.Pow(maneurRadius, 2);

        //если длина касательной не положительна, то мы находимся внутри траектории виража,
        //надо отлетать от корабля, но можно поропбовать зайти на посадку
        if (distanceToTangentPoint <= 0)
        {
            return(carrier.Position);
        }
        distanceToTangentPoint = Mathf.Pow(distanceToTangentPoint, 0.5f);

        //строим основу для касательной от гипотенузы (центр виража - позиция самолета)
        Vector3 toManeurTangent = toManeurCenter.normalized * distanceToTangentPoint;
        //определяем угол между гипотенузой и касательной
        float toManeurTangentRotateSin   = maneurRadius / toManeurCenter.magnitude;
        float toManeurTangetnRotateAngle = Mathf.Asin(toManeurTangentRotateSin) * 180 / Mathf.PI;

        if (signedAngSpeed > 0)
        {
            toManeurTangetnRotateAngle = -toManeurTangetnRotateAngle;
        }
        //для поворота заготовки касательной
        Quaternion rotateToManeurTangent = Quaternion.AngleAxis(toManeurTangetnRotateAngle, Vector3.up);

        //построение касательной от позиции самолета к траектории входа на посадку
        toManeurTangent = rotateToManeurTangent * toManeurTangent;
        //определние точки входа в траекторию посадки
        return(Position + toManeurTangent);
    }