Как сравнить данные преобразования игрового объекта с другими данными преобразования? - PullRequest
0 голосов
/ 08 ноября 2018

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

using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;

namespace AutocompleteSearchField
{
    public class DatabaseSearch : EditorWindow
    {
        [MenuItem("Window/Autocomplete Searchbar/Database Search")]
        static void Init()
        {
            GetWindow<DatabaseSearch>("DataBse Search").Show();
        }

        [SerializeField]
        AutocompleteSearchField autocompleteSearchField;

        private static SearchableEditorWindow hierarchy { get; set; }
        private static List<GameObject> allobj = new List<GameObject>();

        void OnEnable()
        {
            if (autocompleteSearchField == null) autocompleteSearchField = new AutocompleteSearchField();
            autocompleteSearchField.onInputChanged = OnInputChanged;
            autocompleteSearchField.onConfirm = OnConfirm;
        }

        void OnGUI()
        {
            GUILayout.Label("Search Hierarchy", EditorStyles.boldLabel);
            autocompleteSearchField.OnGUI();
        }

        void OnInputChanged(string searchString)
        {
            autocompleteSearchField.ClearResults();
            if (!string.IsNullOrEmpty(searchString))
            {
                allobj = new List<GameObject>();
                allobj.AddRange(UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects());
                foreach (GameObject obj in allobj)
                {
                    if (HasAllComponents(obj, typeof(MeshRenderer), typeof(BoxCollider))
                        && CompareTransformsData(obj) == false)
                    {
                        autocompleteSearchField.AddResult(obj.ToString());
                    }
                }
            }
        }

        void OnConfirm(string result)
        {
            var obj = AssetDatabase.LoadMainAssetAtPath(autocompleteSearchField.searchString);
            Selection.activeObject = obj;
            EditorGUIUtility.PingObject(obj);
        }

        public static bool HasAllComponents(GameObject gameObject, params System.Type[] types)
        {
            for (int i = 0; i < types.Length; i++)
            {
                if (gameObject.GetComponent(types[i]) == null)
                    return false;
            }

            return true;
        }

        public static bool CompareTransformsData(GameObject objToCompare)
        {
            List<GameObject> results = allobj;
            bool identical = true;

            foreach(GameObject obj in results)
            {
                if (GameObject.ReferenceEquals(obj, objToCompare))
                {
                    return identical;
                }
            }

            return identical;
        }

        public const int FILTERMODE_ALL = 0;
        public const int FILTERMODE_NAME = 1;
        public const int FILTERMODE_TYPE = 2;

        public static void SetSearchFilter(string filter, int filterMode)
        {
            SearchableEditorWindow[] windows = (SearchableEditorWindow[])Resources.FindObjectsOfTypeAll(typeof(SearchableEditorWindow));

            foreach (SearchableEditorWindow window in windows)
            {
                if (window.GetType().ToString() == "UnityEditor.SceneHierarchyWindow")
                {
                    hierarchy = window;
                    break;
                }
            }

            if (hierarchy == null)
                return;

            MethodInfo setSearchType = typeof(SearchableEditorWindow).GetMethod("SetSearchFilter", BindingFlags.NonPublic | BindingFlags.Instance);
            object[] parameters = new object[] { filter, filterMode, false };
            setSearchType.Invoke(hierarchy, parameters);
        }

    }
}

Но он продолжает добавлять все игровые объекты, даже если они идентичны.

1 Ответ

0 голосов
/ 08 ноября 2018

Вы не получаете желаемый результат из-за сравнения. Не следует сравнивать значения с плавающей запятой / векторы / кватернионы, используя "==". Поскольку они основаны на поплавках и часто они не будут достаточно точными. Даже клонированные объекты будут иметь значения с плавающей запятой 1.000001 или 0.999999.

Лучшим вариантом будет для векторов использовать «Vector3.distance» или «Vector3.Equals», а для Quternions вы можете использовать «Quaternion.Angle» или Quaternion.Equals для проверки соответствующего результата.

т.е. obj.transform.position.Equals(objToCompare.transform.position) & obj.transform.quaternion.Equals(objToCompare.transform.quaternion). Это должно вернуть правильные результаты, но есть вероятность, что результаты могут не совпадать если это произойдет, вы можете использовать

т.е. Vector3.Distance(obj.transform.position, objToCompare.transform.position) < "Margin of difference". Quaternion.Angle(transform.rotation, rotation)<"Margin of difference"

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


Примечание : если вам нужно решение с меньшей нагрузкой на процессор, вам следует использовать (obj.transform.position - objToCompare.transform.position).sqrMagnitude что быстрее чем .Distance, потому что .Distance должна вычислять квадратный корень, который очень медленно.

Вот несколько ссылок для продолжения: Vector3 Сравнить Quaternion Сравнить


Обновление:

public static bool CompareTransformsData(GameObject objToCompare)
{
    List<GameObject> results = allobj;

    foreach (GameObject obj in results)
    {
        //Method 1 using Equal
        if( obj.transform.position.Equals(objToCompare.transform.position) && 
            obj.transform.rotation.Equals(objToCompare.transform.rotation))//Do confirm here if the vectors & quaternions are able to use equal comparer & result is satisfactory to your needs
        {
            return true;
        }

        //Method 2 using sqrmagnitude & Quaternion.angle
        //Use this one if you need more acurate result and control on objects
        //modify the 0.1f paramters for more accuracy and filtering
        if ((obj.transform.position -  objToCompare.transform.position).sqrMagnitude  < 0.1f &&
            Quaternion.Angle(obj.transform.rotation, objToCompare.transform.rotation) < 0.1f)//Do confirm here if the vectors & quaternions are able to use equal comparer & result is satisfactory to your needs
        {
            return true;
        }
    }

    return false;
}

Используйте любой из них, но не используйте оба.

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