[英]GetComponent returning "null" instead of null
如果請求的組件未附加到對象,我對GetComponent
的返回值感到困惑。 根據 Unity 文檔, GetComponent
應該返回 null。 但是,似乎正在發生的是GetComponent
返回請求類型的“null”對象,而不是值null
。
在此示例中,我的游戲對象沒有附加CircleCollider2D
。 當我在CircleCollider2D x = GetComponent<CircleCollider2D>();
行上設置斷點時 ,我得到這個結果
為什么返回值不為null
?
編輯:
另一個編輯:
是不是 Unity 重載了==
運算符,以便GetComponent
始終返回一個對象,但該對象可以具有內部“null”狀態,與null
相比返回 true ? 我可以在UnityEngine
命名空間中看到以下聲明
public static bool operator ==(Object x, Object y);
public static bool operator !=(Object x, Object y);
似乎GetComponent<T>()
不返回TRUE null
。 相反,它返回帶有默認值的新 T,在使用任何空字段時會觸發MissingComponentException
。 GetInstanceID()
和GetHashCode()
之所以有效,是因為它們只使用設置為默認值 0 的int m_InstanceID
。不確定ToString()
是如何工作的,但它可能在m_InstanceID == 0
時返回"null"
。
證明:
void Start()
{
CircleCollider2D getComponent = GetComponent<CircleCollider2D>();
CircleCollider2D empty = null;
CircleCollider2D newCC = new CircleCollider2D();
Debug.LogFormat("getComponent.GetInstanceID() {0}", getComponent.GetInstanceID());
Debug.LogFormat("newCC.GetInstanceID() {0}", newCC.GetInstanceID());
try
{
Debug.LogFormat("empty.GetInstanceID() {0}", empty.GetInstanceID());
}
catch (System.NullReferenceException e)
{
Debug.Log("empty.GetInstanceID() doesnt work, im true null");
}
try
{
string t = getComponent.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("getComponent fires {0} when any field is null",
e.ToString()));
}
try
{
string t = newCC.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("newCC fires {0} when any field is null",
e.ToString()));
}
}
結果:
getComponent.GetInstanceID() 0
newCC.GetInstanceID() 0
empty.GetInstanceID() doesnt work, im true null
getComponent fires UnityEngine.MissingComponentException
newCC fires System.NullReferenceException
還:
getComponent.GetHashCode() = 0
getComponent.ToString() = "null"
為什么getComponent == null
是真的? 通常它只是:
`getComponent.GetInstanceID() == otherComponent.GetInstanceID()`
在o == null
的情況下,它是:
return !(
o.GetCachedPtr() != IntPtr.Zero || (!(o is MonoBehaviour) &&
!(o is ScriptableObject) &&
Object.DoesObjectWithInstanceIDExist(o.GetInstanceID())));
所以我猜 InstanceID = 0 的對象永遠不存在。 如果您想了解更多信息,請搜索反編譯的 UnityEngine/UnityEngine/Object.cs。
會不會是 Unity 重載了 == 運算符
Tldr:是的。
為什么返回值不為空?
當 MonoBehaviour 有字段時,僅在編輯器中,我們不會將這些字段設置為“真正的空”,而是設置為“假空”對象。
為什么? 根據那篇文章,基本上有兩個原因:
在編輯器模式下:獲取有關調用的更多上下文信息,因此如果您有異常,您將能夠知道哪個對象是原因。
來自UnityEngine.Object
的所有內容都包裝在 C# 對象中,以保留對 Unity C/C++ GameEngine 對象的引用。 在編輯器/代碼中,我們使用 C# 元素,但這些只是對“真實”c++ 對象的引用。 現在,那些“真正的”c++ 對象的生命周期被顯式處理(如果你destroy
C++ 對象,它將被銷毀,分配的內存將被釋放)但是當垃圾收集器決定釋放時,C# 對象將被完全銷毀那個記憶。 因此,您將有一個指向空 C++ 對象的非空 C# 對象。 使用這個假的 null技巧,您將知道這個特定的 C# 對象為null
,因為在 C++ 端它被破壞了。
當你有一個單例並且if (sm_Instance == null)
沒有按預期工作時,這也很重要,你可以使用: if (EqualityComparer<T>.Default.Equals(sm_Instance, null))
instad。
編輯:如果您的單例使用泛型並且您的類型約束是class
,這可能會導致
public class Singleton<T> where T : class {
這將導致使用類對象的==
運算符,即使您的單例是 GameEngine 對象。 一個解決方案? 您可以使用UnityEngine.Object
而不是class
,例如:
public class Singleton<T> where T : UnityEngine.Object {
相關主題:
https://forum.unity3d.com/threads/null-check-inconsistency-c.220649/#post-1775701
ps:如果你去UnityEngine.Object組裝,你就能看到重載:
快到最后了……
如果您仍在尋找解決方案,這對我有用`
var component = parent.GetChild(i).GetComponent<T>();
if(component != null)
{
if (component.ToString().Equals("null") == false)
{
list.Add(component);
}
}
GetComponent
應返回 'Component 類型的對象. Hence it is not expected to return "null" rather ~null
. Hence it is not expected to return "null" rather ~null
是預期值。 也許這種奇怪的行為應該報告給unity3d
,
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.