【问题标题】:How can I compare a gameobject transform data to other transforms data?如何将游戏对象转换数据与其他转换数据进行比较?
【发布时间】:2019-04-11 09:55:39
【问题描述】:

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

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

    }
}

但即使相同,它也会继续添加所有游戏对象。

【问题讨论】:

  • 当前您正在检查列表中的对象是否与同一列表中的任何对象相同。这当然会返回所有对象。我不确定你想在这里实现什么..?
  • 你想比较什么?您只有一个List,并且您正在将该列表中的所有内容相互比较。如所写,要么至少有一个元素与其他元素不同,您将添加所有内容,或者它们都相同,您将不添加任何内容。你想做什么?
  • 我想要做的是 List allobj 包含许多游戏对象,我希望从这个 List 中添加到 AddResult 中的游戏对象只有 HasAllComponents 和不同的游戏对象。它们可以是相同的名称,例如 Cube 和 Cube,但位置、旋转或父级不同。 HasAllComponents 工作正常,问题是如何不向 AddResult 添加相同的对象。例如,如果我有一个立方体并且我复制了立方体,那么只添加一个立方体,但如果我有 3 个同名但位置或旋转不同的立方体,则添加所有立方体。

标签: c# unity3d


【解决方案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) &lt; "Margin of difference"Quaternion.Angle(transform.rotation, rotation)&lt;"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;
}

使用其中之一,但不要同时使用。

【讨论】:

  • 你能告诉我如何在我的代码中做到这一点吗?我已使用完整代码编辑并更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 2016-01-28
相关资源
最近更新 更多