Unity3d - получает высоту GameObject для вращающегося объекта - PullRequest
0 голосов
/ 09 мая 2018

Я хочу получить рост GameObject. Я пытался с:

this.GetComponent<MeshRenderer>().bounds.size.y

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

Это ограничивающая ось ограничивающая рамка (также известная как «AABB»).

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

enter image description here

У кого-нибудь еще была такая проблема?

Какой-нибудь совет, как точно определить высоту объекта?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Решение 1: Используйте Mesh.bounds

Вы можете получить высоту, используя Mesh.bounds. В отличие от MeshRenderer.bounds (или Renderer.bounds), это ограничивающий ось ограничивающий прямоугольник сетки в его локальном пространстве (т.е. не подвержен преобразованию).

Вам по-прежнему необходимо учитывать масштаб объекта GameObject, используя transform.lossyScale следующим образом:

public class Example : MonoBehaviour
{
    private Mesh _mesh;

    private void Awake()
    {
        _mesh = GetComponent<MeshFilter>().mesh;
    }

    private void Update()
    {
        float height = _mesh.bounds.size.y * transform.lossyScale.y;
        Debug.Log(height);
    }
}

(Обратите внимание, что при использовании transform.lossyScale значение может быть немного неточным. Это то, на что следует обратить внимание, если вам нужна предельная точность. См. документацию по transform.lossyScale :)

Обратите внимание, что если у вас есть родительское преобразование со шкалой и ребенок то, что произвольно повернуто, масштаб будет перекошен. Таким образом, масштаб может не будет правильно представлен в 3-компонентном векторе, а только в 3х3 матрица. С таким представлением неудобно работать тем не мение. lossyScale - это удобное свойство, которое пытается сопоставить фактический мировой масштаб, насколько это возможно. Если ваши объекты не искаженное значение будет полностью правильным и, скорее всего, значение не будет сильно отличаться, если он также содержит перекос.


Решение 2 (Обходной путь): Кэшировать необращенные границы MeshRenderer

В качестве альтернативы, если в вашем контексте вы можете создать экземпляр GameObject без поворота и вам нужно только повернуть GameObject после инициализации, одним из обходных решений является кэширование границ из MeshRenderer в Awake метод, следующий:

public class Example : MonoBehaviour
{
    private Bounds _initialUnrotatedBounds;

    private void Awake()
    {
        InitializeUnrotatedBounds();
    }

    private void InitializeUnrotatedBounds()
    {
        Assert.IsTrue(transform.rotation == Quaternion.identity);

        _initialUnrotatedBounds = GetComponent<MeshRenderer>().bounds;
    }

    private void Update()
    {
        // Use the cached bounds. Now, even for moving objects,
        // it doesn't matter if the rotation changes
        float height = _initialUnrotatedBounds.size.y;
        Debug.Log(height);
    }
}
0 голосов
/ 09 мая 2018

Один из вариантов - использовать коллайдер игрового объекта.

Вы можете относительно легко найти высоту и ширину коллайдера, так что это один из способов измерения размеров игрового объекта. Коллайдер, например коробчатый коллайдер на игровом объекте, должен будет полностью охватывать объект. Вы можете сделать это, изменяя размеры коллайдера, пока он не будет плотно обернут вокруг вашего игрового объекта. Затем, когда вы хотите найти определенное измерение объекта, вместо этого найдите это измерение на коллайдере и умножьте на transform.scale игрового объекта.

Вот несколько примеров, которые я протестировал.

Пример 1:

CapsuleCollider m_Collider = GetComponent<CapsuleCollider>();
var height = m_Collider.height  * transform.localScale.y;

https://docs.unity3d.com/ScriptReference/CapsuleCollider-height.html

или

Пример 2:

   BoxCollider m_Collider = GetComponent<BoxCollider>();
   var height = m_Collider.size.y  * transform.localScale.y;
   var width = m_Collider.size.x  * transform.localScale.x;
   var breadth = m_Collider.size.z  * transform.localScale.z;

https://docs.unity3d.com/ScriptReference/BoxCollider-size.html

Надеюсь, одна из них подойдет вам.

Если нет, то второй неудобный способ определения высоты - создать 2 прокси-объекта в качестве дочерних элементов вверху и внизу вашего объекта. Затем найдите скалярное расстояние между ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...