Применение направления к текущей позиции преобразования

Я не совсем уверен, правильно ли я выбрал заголовок для вопроса, не стесняйтесь редактировать его, если вы считаете, что он вводит в заблуждение.

Я разрабатываю экшн-игру, в основе игрового процесса которой лежит музыка. Он содержит набор сущностей (игровых объектов), которые движутся в нескольких направлениях; верхние, правые, левые, нижние и диагональные движения (например, верхнее левое, верхнее правое, нижнее левое и т. д. и т. д.).

Чтобы определить положение этих сущностей, необходимо рассчитать значение, включающее темп музыки и несколько свойств самих сущностей, которые я могу создать в Unity.

Я использую следующую функцию для определения положения преобразования объектов:

    private Vector3 _position;

    private void DeterminePosition(float offset)
    {
        // In actual code, the _position is initialized under Start() method
        // But for this simplification sake, I'll just put it here
        _position = _position == null ? new Vector3(0, 0, 1f) : _position;

        if (Direction == Direction.Up || Direction == Direction.RightUp || Direction == Direction.LeftUp)
        {
            _position.y = offset;
        }
        if (Direction == Direction.Down || Direction == Direction.RightDown || Direction == Direction.LeftDown)
        {
            _position.y = -offset;
        }
        if (Direction == Direction.Left || Direction == Direction.LeftDown || Direction == Direction.LeftUp)
        {
            _position.x = -offset;
        }
        if (Direction == Direction.Right || Direction == Direction.RightDown || Direction == Direction.RightUp)
        {
            _position.x = offset;
        }

        transform.position = _position;
    }

Где offset — это значение, о котором я говорил ранее.

Код работает отлично, как и предполагалось, однако игру нужно изменить. Вместо фиксированного направления (например, вверх, вправо, влево, снизу, вправо вверх, вниз влево и т. д. и т. д.) мы решили использовать значение градуса для направления (от 0 до 360 градусов).

И теперь я понятия не имею, как этому воспрепятствовать. Я пытался использовать следующие коды, но это не работает:

    _position = new Vector3(offset, offset, transform.position.z);

    // Where the direction is between 0 .. 360
    transform.position = Quaternion.Euler(0, direction, 0) * _position;

Кто-нибудь еще может предложить решение?
Заранее спасибо!


person CXO2    schedule 07.08.2017    source источник


Ответы (1)


Если offset представляет собой расстояние от новой позиции до (0, 0, transform.position.z) (называя это исходной точкой, поскольку кажется, что изменяются только позиции x и y), а direction представляет собой угол, измеренный против часовой стрелки в градусах между положительной осью x и вектором от начала координат до новую позицию, вы можете получить новые позиции x и y, используя offset и sin и cos для direction:

_position.x = offset * Mathf.Cos(Mathf.Deg2Rad * direction);
_position.y = offset * Mathf.Sin(Mathf.Deg2Rad * direction);
_position.z = transform.position.z; //assuming the z position stays the same
transform.position = _position;

Изменить

Чтобы учесть масштабирование, я думаю, вам нужно будет заменить offset в зависимости от direction.

float multiplier = 0f;
if(0 <= direction && direction <= 45)
{
    multiplier = Mathf.Abs(offset / Mathf.Cos(Mathf.Deg2Rad * direction));
}
else if(45 < direction && direction <= direction <= 135)
{
    multiplier = Mathf.Abs(offset / Mathf.Sin(Mathf.Deg2Rad * direction));
}
else if(135 < direction && direction <=225)
{
    multiplier = Mathf.Abs(offset / Mathf.Cos(Mathf.Deg2Rad * direction));
}
else if(225 < direction && direction <= 315)
{
    multiplier = Mathf.Abs(offset / Mathf.Sin(Mathf.Deg2Rad * direction));
}
else if(315 < direction && direction <= 360)
{
    multiplier = Mathf.Abs(offset / Mathf.Cos(Mathf.Deg2Rad * direction));
}

_position.x = multiplier * Mathf.Cos(Mathf.Deg2Rad * direction);
_position.y = multiplier * Mathf.Sin(Mathf.Deg2Rad * direction);
_position.z = transform.position.z;
transform.position = _position;

Это разобьет координатную плоскость на 4 секции по 90 градусов (если вы объедините 315 < direction <= 360 и 0 <= direction < 45), где вы используете sin или cos от direction для создания множителя, который должен учитывать для областей, где offset необходимо масштабировать в зависимости от x и y компонентов смещения.

person Poosh    schedule 07.08.2017
comment
Спасибо за ваш ответ, это ПОЧТИ правильно (это действительно работает, но ..) Я забыл упомянуть, что форма игровой арены квадратная, а не круглая. В моей предыдущей реализации до использования степени, когда объект входит в угол (верхний левый, верхний правый и т. д.), позиция преобразования совпадает с темпом (когда смещение музыки достигает 0, объект достигает границы арены). Однако, когда я обновляю вашу реализацию, объект кажется немного медленнее, смещение музыки достигает 0, но объект даже не достигает границы арены. Это несколько превращает арену в круг, а не в квадрат. - person CXO2; 07.08.2017
comment
Однако, если объект движется прямо вперед, позиция преобразования и смещение музыки кажутся совпадающими (например, направление составляет 180 градусов). - person CXO2; 07.08.2017
comment
Следующее изображение описывает, что происходит: imgur.com/e780D88 или это: imgur.com/tmLY4Pt - person CXO2; 07.08.2017
comment
Привет @SirusDoma. Каковы границы арены? Я думаю, что offset нужно масштабировать. Если объект имеет direction, который делит 90 (движется только в направлении, параллельном оси X или Y), величина transform.position будет равна offset. Раньше, если объект двигался по диагонали, величина transform.position была бы sqrt(2) * offset, но теперь величина всегда будет offset, независимо от направления, поэтому теперь расстояние будет короче. - person Poosh; 07.08.2017
comment
границы арены - это просто визуальное представление, расстояние между центром арены (где появляется сущность) и границей составляет 5f (я действительно не знаю, какой тип измерения в единстве). Тогда как настроить (или масштабировать) его? также кажется, что sin и cos находятся в неправильном порядке, кажется, что это sin для x и cos для y - person CXO2; 07.08.2017
comment
Я посмотрю на это еще немного; то, что вы описываете, звучит как результат того, что максимальное расстояние теперь составляет offset. Одна вещь, которую, возможно, стоит быстро попробовать, это заменить offset в уравнениях на Mathf.Abs(offset / Mathf.Cos(Mathf.Deg2Rad * direction)). При direction == 45 результат будет sqrt(2) * offset, а при direction == 0 результат будет offset. (Я не уверен насчет значений между ними; все еще нужно исследовать. Кроме того, следите за делением на 0). - person Poosh; 08.08.2017
comment
Я попробовал вашу формулу, и она действительно возвращает то, что вы ожидаете, когда direction равно 45, смещение равно sqrt(2) * offset, а когда direction равно 0, результат равен offset. Однако сущность движется слишком быстро, особенно в определенном направлении... - person CXO2; 08.08.2017