LoginSignup
7
6

More than 5 years have passed since last update.

UnityEngine.ObjectとSystem.Objectの注意点

Posted at

UnityEngine.ObjectとSystem.Objectはキャストできます。

UnityEngine.Objectコード抜粋

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine.Internal;
using UnityEngineInternal;
namespace UnityEngine
{
    [StructLayout(LayoutKind.Sequential)]
    public class Object
    {
        private int m_InstanceID;
        private IntPtr m_CachedPtr;
        private string m_UnityRuntimeErrorString;
        public extern string name
        {
略...

これはUnity側でどうこうしてるというわけではなく、C#の言語機能になります。
C#はあらゆるクラスは基底クラスとしてSystem.Objectを継承しているという言語仕様があります。
Unityは.Net(C#)を使っています。そのため、C#仕様に則り先ほどのコードは暗黙的にSystem.Objectを継承しています。

実はこうなっている
namespace UnityEngine
{
    [StructLayout(LayoutKind.Sequential)]
    public class Object : System.Object {}

そのためUnityEngine.ObjectはSystem.Objectにキャスト可能になっています。

しかし、このせいでいくつか注意しておくべきことがあったのでまとめておきます。

自作クラスはUnityEngine.Objectにキャストできない

例えば次のような自作クラスがあったとして、

自作クラスだよ
public class Hoge
{

}

これはSystem.Objectクラスを暗黙的に継承しています。

そのためUnityEngine.Objectにキャストしようとするとエラーが発生します。

キャスト失敗
Hoge hoge = new Hoge ();
UnityEngine.Object hoge2UnityEngine = (UnityEngine.Object)hoge; //コンパイルエラー発生
System.Object hoge2System = (System.Object)hoge; //OK

そりゃそうですよね。
もしUnityEngine.ObjectにキャストしたいならUnityEngine.Objectを継承させればOKです

キャストできるよ
public class Piyo : UnityEngine.Object
{

}
Piyo piyo = new Piyo ();
UnityEngine.Object piyo2UnityEngine = (UnityEngine.Object)piyo; //OK
System.Object piyo2System = (System.Object)piyo; //OK

間違いやすいので注意しましょう。

自作コンポーネントはUnityEngine.Objectにキャストできる

例えばこんなコンポーネントがあったとして、

自作コンポーネント
using UnityEngine;

public class Test :MonoBehaviour
{

    void Start ()
    {

    }
}

自作コンポーネントはUnityEngine.ObjectにもSystem.Objectにもキャストできます。
自作コンポーネントの継承関係は次のようになっています。

自作 -> MonoBehaviour  -> Behavior  -> Component  -> UnityEngine.Object  -> System.Object

UnityEngine.ObjectもSystem.Objectも継承しています。
そのため2つともキャストできるのです。

UnityEngine.Objectはいろいろオーバーライドしています。

toString関数
        [WrapperlessIcall]
        [MethodImpl(MethodImplOptions.InternalCall)]
        public override extern string ToString();
Equals関数
        public override bool Equals(object o)
        {
            return Object.CompareBaseObjects(this, o as Object);
        }
GetHashCode
        public override int GetHashCode()
        {
            return this.GetInstanceID();
        }
その他
        public static implicit operator bool(Object exists)
        {
            return !Object.CompareBaseObjects(exists, null);
        }
        public static bool operator ==(Object x, Object y)
        {
            return Object.CompareBaseObjects(x, y);
        }
        public static bool operator !=(Object x, Object y)
        {
            return !Object.CompareBaseObjects(x, y);
        }

FindObjectOfType関数は自作クラスには使えない

FindObjectOfTypeのコードをみると次のようになっています。

lang: FindObjectOfType
public static T FindObjectOfType<T>() where T : Object
{
return (T)((object)Object.FindObjectOfType(typeof(T)));
}

where T : ObjectのObjectはUnityEngine.Objectを指します。
自作クラスは基本的にはSystem.Objectを直接継承しているのでFindObjectOfTypeに使うことはできません。

各種注意しましょう。
UnityEngine.ObjectとSystem.Object紛らわしい・・・

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6