Перемещение символа в Unity3D на основе входа акселерометра

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

if (Input.acceleration.y > -0.2f && Input.acceleration.y < 0.2f) {
                        maxSpeed = 17;
                }

        if (Input.acceleration.y > -0.5f && Input.acceleration.y < -0.2f) {
            maxSpeed = 25;
        }
        if (Input.acceleration.y > 0.2f && Input.acceleration.y < 0.5f) {
            maxSpeed = 25;
        }
        if (Input.acceleration.y > -0.7f && Input.acceleration.y < -0.5f) {
            maxSpeed = 25;
        }
        if (Input.acceleration.y > 0.5f && Input.acceleration.y < 0.9f) {
            maxSpeed = 25;
        }
        if (Input.acceleration.y < -0.9f) {
            maxSpeed = 40;
        }
        if (Input.acceleration.y  > 0.9f) {
            maxSpeed = 40;
        }

В основном, чем дальше устройство наклоняется, тем быстрее перемещается символ. Я уверен, что есть лучший способ написать этот код, но я довольно ужасен в математике, и я не могу понять это. Любые предложения по его очистке немного?

11 голосов | спросил lukas 31 J000000Thursday14 2014, 09:35:20

5 ответов


10

Я ничего не знаю о или , поэтому, если есть специальная помощь на языке, Я понятия не имею об этом!

Я замечаю, что каждое условие проверяет Input.acceleration.y, так что это один бит информации, который повторяется. Я также замечаю, что у нас три скорости, но у нас есть семь условностей!

Прежде всего, негативы сбивают с толку. Сначала найдите абсолютное значение.

Я собираюсь принять число, за которым следует «f» означает float. Возможно, нам нужно что-то вроде:

float acceleration = Math.Abs(Input.acceleration.y);

Отлично, теперь с этим будет легче справиться!

Теперь нам нужна простая проверка:

if (acceleration < 0.2f) {
    maxSpeed = 17;
} else if (acceleration < 0.9f) {
    maxSpeed = 25;
} else {
    maxSpeed = 40;
}

Ваши исходные номера были немного странными, но если вы имели в виду такой странный образец, исправьте меня!

ответил Alex L 31 J000000Thursday14 2014, 10:04:58
7

Вот ваша номерная строка:

  …<-40->|      |<-25->|<--25-->|<-17->|<-17->|<--25-->|<----25----->|<-40->…
        -0.9  -0.7   -0.5     -0.2     0    +0.2     +0.5          +0.9

Первая вероятная ошибка, которую я вижу, заключается в том, что диапазоны являются прерывистыми. Например, если Input.acceleration.y равен точно 0.5, то ни один из случаев не применяется.

Как только вы исправите эту ошибку, вы можете упростить цифровую строку до следующего эквивалента:

  …<-40->|      |<------25----->|<-----17---->|<---------25--------->|<-40->…
       -0.9   -0.7            -0.2          +0.2                   +0.9

Следующая вероятная ошибка заключается в том, что обе стороны асимметричны, и существует странный разрыв между -0,9 и -0,7. Возможно, вы хотели заполнить это с помощью maxSpeed = 25? Я предполагаю, что вы имели в виду ...

  …<-40->|<---------25--------->|<-----17---->|<---------25--------->|<-40->…
       -0.9                   -0.2          +0.2                   +0.9

Так как вся числовая строка от -∞ до + ∞ покрыта, вы должны быть в состоянии избежать двойных сравнений неравенства и вместо этого связывать их с else-ifs. Или, если вам нравятся более компактные выражения, вы можете использовать тройные операторы:

float absY = Input.acceleration.y < 0 ? -Input.acceleration.y : Input.acceleration.y;
maxSpeed = (absY < 0.2f) ? 17
         : (absY < 0.9f) ? 25
         :                 40;

Первая строка также может быть написана с использованием Math.Abs() , но я решил написать его таким образом, чтобы избежать преобразования float в double.

ответил 200_success 31 J000000Thursday14 2014, 10:25:55
5

Вам не хватает некоторых случаев, например, что должно произойти, когда y = 0.5? Или -0.9f < y < -0.7?

Я думаю, что это действительное представление вашего текущего кода:

y:   -inf    -0.9f  -0.7f  -0.5f   -0.2f    0.2f    0.5f    0.9f       +inf
m:        40   ?   ?  ?  25  ?   25  ?   17  ?   25  ?   25  ?    40

Основываясь на этой диаграмме, код, отправленный в ответе @ AlexL, вероятен тем, чего вы хотите достичь. Если вы пытаетесь сделать что-то еще, отправьте еще один вопрос с более подробной информацией:)

ответил mjolka 31 J000000Thursday14 2014, 10:20:09
5

Также я предпочитаю отвечать на Alex L, это альтернативный способ

Первые 5 if conditions проверяют, если данный Input.acceleration.y между двумя значениями float.

Итак, мы можем извлечь часть between в метод расширения, например

public static Boolean Between(this float num, float lower, float upper)
{
    return lower < num && num < upper;
}

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

float accelerationY = Input.acceleration.y;

Далее мы используем метод Between ()

    if (accelerationY.Between(-0.2f, 0.2f))
    {
        maxSpeed = 17;
    }
    else if (accelerationY.Between(-0.5f, -0.2f)
        || accelerationY.Between(0.2f, 0.5f)
        || accelerationY.Between(-0.7f, -0.5f)
        || accelerationY.Between(0.5f, 0.9f))
    {
        maxSpeed = 25;
    }
    else if (accelerationY < -0.9f || accelerationY>0.9f)
    {
        maxSpeed = 40;
    }
ответил Heslacher 31 J000000Thursday14 2014, 10:59:24
1

Вы действительно хотите, чтобы скорость движения была инкрементальной? По тому, как вы сформулировали свой вопрос, мне кажется, что вы действительно хотите линейный градиент скорости движения с уровнем наклона устройства.

Вот альтернативный вариант, если это, если вы действительно хотите.

public class CharacterMover : MonoBehaviour
{
    //Declare the max speeds at which the player can move left and right
    private float maxLeftXAxisSpeed = -20f, maxRightXAxisSpeed = 20f;

    //Speed assigned for in-game movement
    private float moveXAxisSpeed = 0f;

    void Update()
    {
        //If the device is tilting
        if(Input.acceleration.y != 0)
        {
            moveXAxisSpeed = ConvertBetweenRanges(Input.acceleration.y, -1f, 1f, maxLeftXAxisSpeed, maxRightXAxisSpeed);
        }           

        //you would want to assign the transform of the gameobject to the moveXAxisSpeed here
    }

    //This is an extension method to convert between two ranges of float values
    private float ConvertBetweenRanges(float oldValue, float oldMin, float oldMax,
                                             float newMin, float newMax)
    {
        float newValue = (((oldValue - oldMin) * (newMax - newMin))/(oldMax - oldMin) + newMin);
        return newValue;
    }
}

Я бы предложил сделать метод ConvertBetweenRanges методом расширения класса float, чтобы вы могли его вызвать из любого места. Как это сделать, это другой вопрос!

ответил Matthew Sawrey 8 PM00000070000004931 2015, 19:11:49

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132