C# GetComponent returning";空";而不是空值
如果请求的组件未附加到对象,我对C# GetComponent returning";空";而不是空值,c#,unity3d,C#,Unity3d,如果请求的组件未附加到对象,我对GetComponent的返回值感到困惑。根据Unity文档,GetComponent应该返回null。但是,GetComponent返回的是请求类型的“null”对象,而不是值null 在本例中,我的游戏对象没有附加CircleCollider2D。当我在CircleCollider2D x=GetComponent()行上设置断点时, 为什么返回的值不是空的 编辑: 另一编辑: 可能是Unity重载了=操作符,使得GetComponent始终返回一个对象,但
GetComponent
的返回值感到困惑。根据Unity文档,GetComponent
应该返回null。但是,GetComponent
返回的是请求类型的“null”对象,而不是值null
在本例中,我的游戏对象没有附加CircleCollider2D
。当我在CircleCollider2D x=GetComponent()行上设置断点时代码>,
为什么返回的值不是空的
编辑:
另一编辑:
可能是Unity重载了=
操作符,使得GetComponent
始终返回一个对象,但是该对象可以有一个内部“null”状态,与null
相比,该状态返回true?我可以在UnityEngine
名称空间中看到以下声明
public static bool operator ==(Object x, Object y);
public static bool operator !=(Object x, Object y);
GetComponent
应返回“Component类型的对象”。因此,它不应返回“null”,而应返回~null
值。也许应该向unity3d报告这种奇怪的行为,似乎GetComponent()
没有返回TRUEnull
。相反,它返回带有默认值的新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==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:是
为什么返回值不为null
根据:
当MonoBehavior具有字段时,仅在编辑器中,我们不设置
这些字段被设置为“真空”,但被设置为“假空”对象
为什么??根据该条,基本上有两个原因:
- 在编辑器模式下:获取有关调用的更多上下文信息,因此如果出现异常,您将能够知道是哪个对象导致了异常
- 来自UnityEngine.Object的每个对象
都包装在一个C#对象中,以保留对Unity C/C++GameEngine对象的引用。在编辑器/代码中,我们使用C元素,但这些只是对“真实”C++对象的引用。现在,显式地处理那些“真实”C++对象的生命周期(如果你是代码>破坏<代码>某个C++对象,它将被破坏,分配的内存将被释放),但是当垃圾回收器决定释放该内存时,C对象将被完全销毁。因此,你将有一个不为零的C++对象指向一个空C++对象。使用这个假null技巧,你会知道这个特定的C对象是<代码> null <代码>,因为在C++端它被破坏了。p>
如果您有一个单例并且
if(sm_Instance==null)
未按预期工作,则这一点也很重要,您可以使用:if(EqualityComparer.Default.Equals(sm_Instance,null))
instad
编辑:如果您的单例使用泛型,并且您的类型约束为class
public class Singleton<T> where T : class {
相关线程:
Ps:如果您转到UnityEngine.Object程序集,您将能够看到重载: 快结束了
然而,似乎发生的是GetComponent返回的是请求类型的“null”对象,而不是null值。
您是如何得出这个结论的?请向我们展示您的代码-如果不看代码,就不可能给您提供好的建议。代码就是CircleCollider2D x=GetComponent()代码>我的唤醒方法中有它。我在那一行上放了一个断点,屏幕截图是在跨过那一行后从Locals窗口中显示的。x.GetType()
返回什么?说真的,你在问题中添加的代码越多,这个过程就变得容易多了。CircleCollider2D
是结构还是类?你能给我们看一下它的源代码吗(也许是通过反编译的)?有帮助吗?是的,Unity论坛上的答案确实有帮助。我很高兴看到这是我想要的行为,我没有发疯。谢谢。实际上default(IntPtr)=IntPtr.Zero
所以o.GetCachedPtr()==IntPtr.Zero
我怀疑这种“奇怪的行为”实际上是故意的。
return !(
o.GetCachedPtr() != IntPtr.Zero || (!(o is MonoBehaviour) &&
!(o is ScriptableObject) &&
Object.DoesObjectWithInstanceIDExist(o.GetInstanceID())));
public class Singleton<T> where T : class {
public class Singleton<T> where T : UnityEngine.Object {