0

我正在尝试复制MonoBehaviourUnity 3D 引擎。我在 Linux 上使用 monodevelop,大多数测试将在 Windows 中完成Unity 3D engine editor

更多关于MonoBehaviour.Update可以在这里阅读

我想在每 10 毫秒Update继承的所有类型上调用该方法。MonoBehavior

这就是我对 Start 的处理方式

using System;
using System.Reflection;
public class MonoBehaviour{

    public static void Main (){
        Type[] types = Assembly.GetExecutingAssembly().GetTypes();

        foreach (Type type in types) {
            if (type.IsSubclassOf(typeof(MonoBehaviour))){

                System.Reflection.MethodInfo mInfo = type.GetMethod ("Start", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null); // it is run 2 times
                if (mInfo != null) {
                    ConstructorInfo ctor = type.GetConstructor (new Type[] { });
                    if (ctor != null) {
                        object inst = ctor.Invoke (new object[] { });
                        mInfo.Invoke (inst, new object[] { });
                    }
                }
            }
        }
    }
}

class example : MonoBehaviour{
    void Start(){
        // this works perfectly
        Console.WriteLine ("HelloWorld");
    }
    void Update(){
        // I want this to be run every 10 ms
        Console.WriteLine ("HelloinUpdate");
    }
}
4

3 回答 3

2

你可以在不使用反射的情况下做到这一点,它会更快(更安全):

using System;
using System.Linq;
using System.Timers;

public static class Program
{
    public static void Main()
    {
        IEnumerable<Type> assemblyTypes = typeof(MonoBehaviour).Assembly.GetTypes();

        IEnumerable<Type> behaviourTypes = assemblyTypes
            .Where(type => typeof(MonoBehaviour).IsAssignableFrom(type))
            .Where(type => !type.IsAbstract);

        List<MonoBehaviour> behaviours = behaviourTypes
            .Select(Activator.CreateInstance)
            .Cast<MonoBehaviour>()
            .ToList();

        foreach (MonoBehaviour monoBehaviour in behaviours)
        {
            monoBehaviour.Start();
        }

        var timer = new Timer(10 /* Milliseconds */);

        timer.Elapsed += (sender, eventArgs) =>
        {
            foreach (MonoBehaviour monoBehaviour in behaviours)
            {
                monoBehaviour.Update();
            }
        };

        timer.Start();

        Console.WriteLine("Press a key to stop.");
        Console.ReadKey();
    }
}

public abstract class MonoBehaviour
{
    public virtual void Start()
    {
    }

    public virtual void Update()
    {
    }

    protected static void Log(string message)
    {
        Console.WriteLine("{0} - {1}", DateTime.Now, message);
    }
}

public class Behaviour1 : MonoBehaviour
{
    public override void Start()
    {
        Log("Behaviour1 - Start");
    }

    public override void Update()
    {
        Log("Behaviour1 - Update");
    }
}

public class Behaviour2 : MonoBehaviour
{
    public override void Start()
    {
        Log("Behaviour2 - Start");
    }

    public override void Update()
    {
        Log("Behaviour2 - Update");
    }
}:

输出将是这样的(我将计时器调整为 1000 毫秒):

输出

于 2014-03-13T12:41:23.967 回答
0

基本上,这样的事情应该可以解决问题:

var timer = new Timer(10);
timer.Elapsed += new ElapsedEventHandler(MonoBehavior.Update);
timer.Start();

它创建一个 10 毫秒的计时器,然后将您的方法绑定到经过的事件并启用计时器倒计时。当它达到 0 时,触发事件并重置时间。

于 2014-03-13T12:26:34.547 回答
0

使用Timer

Timer t = new System.Threading.Timer(Update, this, 10, 10);
于 2014-03-13T12:26:45.263 回答