Конкретно, если условие оценивается неправильно - PullRequest
0 голосов
/ 15 февраля 2019

Issue

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

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

Я отладил это (используя VS2017 и последний выпуск Unity 2018) и обнаружил, что когда я выполняю 'наблюдение' над соответствующим выражением, оно оценивается как true, покапри запуске самого кода он оценивается как false.

Как я пытался его решить

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

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

Соответствующий код

SpriteRenderer Renderer = GetComponent<SpriteRenderer>();

Bounds Bounds = Renderer.bounds;
Vector3 Center = Bounds.center;
Vector3 HalfSize = Bounds.extents;

if (HitPosition.y != int.MinValue)
{
    if (HitPosition.y < Center.y + HalfSize.y && HitPosition.y > Center.y - HalfSize.y)
    {
        HitPosition.y = Center.y + (HalfSize.y * (Center.y < 0 ? 1 : -1));
    }
}
else
{
    HitPosition.y = Random.Range(Center.y - (HalfSize.y * 0.2f), Center.y + (HalfSize.y * 0.9f));
    HitPosition.x += (HitPosition.x < Center.x ? -1 : 1) * HitPosition.x / 100;
}


bool HitOnRight = HitPosition.x >= Center.x + HalfSize.x;
bool HitOnLeft = HitPosition.x <= Center.x - HalfSize.x;

float Angle = 0f;

if (Center.y - HalfSize.y - HitPosition.y >= 0) // <--- Issue
{
    Angle = HitOnLeft ? 135f : (HitOnRight ? -135f : 180f);
}
else
{
    Angle = HitOnLeft ? 90f : (HitOnRight ? -90f : 0f);
}

Ожидаемые результаты

Так как это своего рода универсальный метод, который используется для соответствия нескольким объектам в сцене, я ожидаю, что он будет по-разному оценивать различные

В тех случаях, когда возникает проблема оценки, я ожидаю, чтооцените до true, во всех других случаях он должен (и делает) оценивается до false.

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

После @McAden и другого сотрудника, который удалил его ответ (или удалил его), проблема заключалась в самом вычислении.

Я объясню причину проблемы, в случае, если кто-то вбудущее наступит после этого.

Unity при выводе на печать с использованием функций Debug.LogXXX округляет все значения до 2 десятичных знаков.Я пытался найти официальную документацию, но, как оказалось, это часть самого C #.float (для тех, кто пришел из Java-фона) идентифицируется как объект типа Single, а при печати печатается с использованием метода ToString(), который сужает результат до 2 десятичных знаков.

Этоможет вызвать путаницу при выполнении стандартной печати Debug.LogFormat, поскольку она будет отображать 2 десятичных знака, а в таких случаях, как у меня, разница будет настолько мала, что результат будет округлен до 0.

После более глубокогоОтладка и дальнейшее погружение в фактическое значение разницы, я пришел к точке, где значения, которые я получил, были:
Центр Y Значение: 5.114532
Половина Y Значение: 0,64
Хит Y Значение: 4.474533
Результат разницы: -0.0000001192

Это менее чем идеальный пример, потому что вы можете видеть, что это приведет к разнице -0,000001, до сих пор было много случаев, которые привели к тому, что казалось абсолютным0.

  • Для правильного сравнения необходимо соблюдать официальную документацию C # ,который диктует:

    В случаях, когда потеря точности может повлиять на результат сравнения, вы можете использовать следующие методы вместо вызова метода Equals или CompareTo:

    Call Math.Round метод, чтобы оба значения имели одинаковую точность.В следующем примере модифицируется предыдущий пример для использования этого подхода так, чтобы два дробных значения были эквивалентны.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          float value1 = .3333333f;
          float value2 = 1.0f/3;
          int precision = 7;
          value1 = (float) Math.Round(value1, precision);
          value2 = (float) Math.Round(value2, precision);
          Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
       }
    }
    // The example displays the following output:
    //        0.3333333 = 0.3333333: True
    
  • Другой подход заключается в реализации IsApproximatelyEqual;

    Проверка приблизительного равенства вместо равенства.Этот метод требует, чтобы вы определяли либо абсолютную величину, на которую эти два значения могут различаться, но все равно быть равными, либо определяете относительную величину, на которую меньшее значение может отклоняться от большего значения.

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

Спасибо за вашу помощьНадеюсь, никто не столкнется с такой глупостью:)

0 голосов
/ 15 февраля 2019

Приоритет оператора.Попробуйте несколько скобок.

    if ((Center.y - HalfSize.y - HitPosition.y) >= 0) // <--- Issue
    {
        Angle = HitOnLeft ? 135f : (HitOnRight ? -135f : 180f);
    }
    else
    {
        Angle = HitOnLeft ? 90f : (HitOnRight ? -90f : 0f);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...