1

特にUnityエンジンが行うことに気付いたc#で何かを行う方法を理解しようとしています。なんらかの実装またはサブクラス化のように見えますが、ソースがないためわかりません。

Unity では、すべてのスクリプトは次のようになります。

class someclass : MonoBehavior
{
}

これで、この MonoBehavior を介してエンジンが次のようなクラスで呼び出す、使用できる関数のリストがあります。

void OnGUI()
{
  so something here
}

したがって、OnGUI 関数をすべて含む 5 つのスクリプトがある場合、5 つのスクリプトすべてで呼び出されます。

この種のものを自分で実装したいのですが、これを理解できません。

基本クラスまたは実装、またはサブクラスで事前定義された関数を呼び出すが、関数のサブクラスを必要とせず、それらでオーバーライドを使用する必要がないものをどのように作成しますか?

Unity Engine のソース ファイルの例を次に示します。

public class EnemyAttack : MonoBehaviour {
    // Use this for initialization
    void Start () {
        AttackTimer = 0;
        CoolDown = 2.0f;
     }
     // Update is called once per frame
     void Update () {
         if (AttackTimer > 0) AttackTimer -= Time.deltaTime;
         if (AttackTimer < 0) AttackTimer = 0;

         if (AttackTimer == 0){
             Attack();
             AttackTimer = CoolDown;
          }
    }
}

そのコードは完全に機能し、最初の起動時にエンジン呼び出しが開始され(単一の呼び出し)、Update every frameを呼び出しますそのコードのどこにもオーバーライドが絶対にないことに注意してください

ある種のイベント システムのようですが、Google でこれを行う方法を説明しているものは見つかりません。

4

5 に答える 5

3

キーワードを使用したくない/使用できない場合は、overrideReflectionを使用してこれを行うことができます(おそらくdynamicキーワードを使用して)

基本クラス「simply」は、派生クラスで特定のシグニチャ/属性を検索し、メソッドを呼び出します。

これを自分で作成する場合は、リフレクションの結果をキャッシュすることを検討し(またはdynamic、キャッシュを実行する可能性のあるキーワードを使用して)、期待どおりのパフォーマンスが得られるかどうかをテストします。反射が非常に遅くなる可能性があります。この質問も参照してください:ダイナミックラング。ランタイムとリフレクション

例:

class TheBehavior
{
    public void Act()
    {
        dynamic derived = this;
        try
        {
            derived.Foo(42);
            derived.Foob(43);
        }
        catch (RuntimeBinderException e)
        {
            Console.WriteLine("Method call failed: " + e.Message);
        }
    }
}

class TheDerived : TheBehavior
{
    public void Foo(int bar)
    {
        Console.WriteLine("Bar: " + bar);
    }
}

class Program
{
    static void Main(string[] args)
    {
        TheBehavior behavior = new TheDerived();
        behavior.Act();
        Console.ReadKey(true);
    }
}
于 2013-03-15T09:04:35.693 に答える
1

仮想メソッドを使用していないため、最も可能性の高い方法はリフレクションを使用することです。クラスはそのMonoBehaviorサブクラスを反映し、正しいパターンに一致する名前を持つメソッドを検索します。

public class MonoBehavior
{
    private void InitSubclass()
    {
        var methods = new[] { "OnGUI", "OnLoad" }; //etc
        foreach (string methodName in methods)
        {
            MethodInfo method = this.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
            if (method != null)
            {
                method.Invoke(this, new object[0]);
            }
        }
    }
}
于 2013-03-15T09:23:27.210 に答える
0

基本クラスや実装、またはサブクラスで事前定義された関数を呼び出すが、関数にサブクラスを必要とせず、オーバーライドを使用する必要がないものをどのように記述しますか?

私が理解していることから、それらは単なるvirtual方法です。基本クラスはいくつかの基本実装を定義するかもしれませんが、それらのメソッドをオーバーライドするために派生クラスを必要としません。

于 2013-03-15T09:05:24.770 に答える
0

あなたが言っていることを理解しているなら、あなたが探しているのは継承を持つ基本クラスだと思います:

public class BaseClass // or abstract
{
    public void foo(int x)
    {
        //your implementation
    }
}

public class ChildClass : BaseClass
{
    public void foo(int x) : base(x)
    {
        //your implementation
    }
}
于 2013-03-15T09:08:15.707 に答える
0

とを使用virtualoverrideます。

class Program
{
    static void Main(string[] args)
    {
        MyBaseClass ext1 = new Ext1();
        ext1.DoSomething();

        MyBaseClass ext2 = new Ext2();
        ext2.DoSomething();

        Console.ReadKey(true);
    }
}

class MyBaseClass
{
    public void DoSomething()
    {
        DoSomethingBase();
    }

    protected virtual void DoSomethingBase()
    {
        Console.WriteLine("DoSomethingBase");
    }
}

class Ext1 : MyBaseClass
{

}

class Ext2 : MyBaseClass
{
    protected override void DoSomethingBase()
    {
        Console.WriteLine("Overridden DoSomethingBase");
    }
}

クラスは基本のExt1動作をオーバーライドしないためDoSomethingBase()、基本クラスから使用されます。Ext2基本メソッドをオーバーライドするため、オーバーライドされたメソッドが呼び出されます。このコードは次を出力します。

DoSomethingBase
Overridden DoSomethingBase

クラスは、基本クラス自体のインスタンス化を防止するようMyBaseClassにマークすることもできます。abstract

于 2013-03-15T09:08:32.503 に答える