如何将游戏对象转换数据与其他转换数据进行比较?

时间:2018-11-07 21:57:02

标签: c# unity3d

我有一个GameObjects列表,我想将每个游戏对象与List游戏对象进行比较,如果它们不相同,则将其添加为结果。名称可以相同,但如果位置或旋转等参数不相同,则将游戏对象添加为结果即可。

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 :(得分:1)

由于比较器,您没有得到想要的结果。您不应使用“ ==”来比较浮点值/向量/四元数。由于它们基于浮点数,因此很多时候它们不够准确。甚至克隆的对象也将具有浮点值1.000001或0.999999。

更好的选择是对于矢量使用“ Vector3.distance”或“ Vector3.Equals”,对于四元数,可以使用“ 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"

您可以指定自己的值,例如允许的差额。


  

注意:如果您想要较少的CPU密集型解决方案,则应使用   (obj.transform.position - objToCompare.transform.position).sqrMagnitude比   .Distance因为.Distance必须计算平方根,即   真的很慢。

以下是一些后续链接: Vector3 Compare Quaternion Compare


更新

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;
}

使用其中任何一个,但不要同时使用。