【问题标题】:C# Delta Time ImplementationC# 增量时间实现
【发布时间】:2014-09-29 22:59:05
【问题描述】:

这是我尝试制作 2D 粒子模拟的代码 sn-p

static long lastTime = 0;
static double GetDeltaTime()
{
    long now = DateTime.Now.Millisecond;
    double dT = (now - lastTime); // / 1000
    lastTime = now;
    Console.WriteLine(dT);
    return dT;
}

很明显,它将返回自上次调用该方法以来的时间(以毫秒为单位)。唯一的问题,这是它打印的内容

393
1
0
0
0
0
0
0
0
0
0
...

好吧,也许这只是因为每次通过时间不到一毫秒。所以我把它改成了

    static long lastTime = 0;
    static double GetDeltaTime()
    {
        long now = DateTime.Now.Ticks; // Changed this to ticks
        double dT = (now - lastTime); // / 1000
        lastTime = now;
        Console.WriteLine(dT);
        return dT;
    }

但还是会打印出来

6.35476136625848E+17
20023
0
0
0
0
0
0
...

如果“粒子模拟器”不能很好地表明我的程序有多复杂,我只想说,完成一次通过需要比 0 滴答声更长的时间!

那么这里发生了什么?

------- 代码参考 ------ 以下全班仅供参考

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace _2D_Particle_Sim
{
    static class Program
    {
        public static Particle2DSim pSim;
        static Form1 form;
        public static Thread update = new Thread(new ThreadStart(Update));

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]

        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            form = new Form1();

            pSim = new Particle2DSim(form);
            pSim.AddParticle(new Vector2(-80, -7), 5);
            pSim.AddParticle(new Vector2(8, 7), 3);

            Console.WriteLine("Opening Thread");

            Program.update.Start();

            Application.Run(form);

            // System.Threading.Timer timer;
            // timer = new System.Threading.Timer(new TimerCallback(Update), null, 0, 30);
        }

        static void Update()
        {
            GetDeltaTime();
            while (true)
            {
                pSim.Update(GetDeltaTime());
            }
        }

        static long lastTime = 0;
        static double GetDeltaTime()
        {
            long now = DateTime.Now.Ticks;
            double dT = (now - lastTime); // / 1000
            lastTime = now;
            Console.WriteLine(dT);
            return dT;
        }
    }
}

另外,如果我对代码复杂程度的类比还不够,这里是 Particle2DSim 类的更新方法

    public void Update(double deltaTime)
        {
              foreach (Particle2D particle in particles)
              {
                  List<Particle2D> collidedWith = new List<Particle2D>();

                  Vector2 acceleration = new Vector2();
                  double influenceSum = 0;

                  // Calculate acceleration due to Gravity
                  #region Gravity
                  foreach (Particle2D particle2 in particles)
                  {
                      double dist2 = particle.position.Distance2(particle.position);
                      double influence = dist2 != 0 ? particle2.mass / dist2 : 0;
                      acceleration.Add(particle.position.LookAt(particle2.position) * influence);
                      influenceSum += influence;

                      if (dist2 < ((particle.radius + particle2.radius) * (particle.radius + particle2.radius)) && dist2 != 0)
                      {
                          collidedWith.Add(particle2);
                      }
                  }
                  acceleration.Divide(influenceSum);
                  #endregion

                  particle.Update(deltaTime);

                  // Handle Collisions
                  #region Collisions
                  if (collidedWith.Count > 0)
                  {
                      Console.WriteLine("Crash!");

                      double newMass = 0;
                      double newRadius = 0;

                      Vector2 newPosition = new Vector2();
                      Vector2 newVelocity = new Vector2();

                      newMass += particle.mass;
                      newRadius += Math.Sqrt(particle.radius);

                      newPosition += particle.position;

                      newVelocity += particle.velocity * particle.mass;

                      particles.Remove(particle);

                      foreach (Particle2D particle2 in collidedWith)
                      {
                          newMass += particle2.mass;
                          newRadius += Math.Sqrt(particle2.radius);

                          newPosition += particle2.position;

                          newVelocity += particle2.velocity * particle2.mass;

                          particles.Remove(particle2);
                      }

                      newPosition.Divide(collidedWith.Count + 1);
                      newVelocity.Divide(newMass);

                      AddParticle(newPosition, newVelocity, newMass, newRadius);
                  }
                  #endregion
              } 
        }

【问题讨论】:

  • 你有没有试过不使用while(true)并睡一会儿?无论如何,你最终都会想要这样做。
  • 注意Millisecond 是从0999。 (由于您使用long,您可以预计它是总毫秒数。)

标签: c# time timedelta


【解决方案1】:

问题在于您正在使用DateTime 来尝试衡量时间的流逝。 DateTime 用于表示日期和时间,但不用于测量经过的时间。

使用stopwatch 类来测量时间:

Stopwatch sw = new Stopwatch();

sw.Start();

// Do something here

sw.Stop();

Console.WriteLine(sw.ElapsedMilliseconds);
// or sw.ElapsedTicks

有关差异的更多详细信息,请查看 Eric Lippert 的博客HERE

【讨论】:

  • 秒表可能很难在增量上下文中使用。否则不是一个坏建议,它可以工作。
【解决方案2】:

DeltaTime 就像 Unity 中的一样

using System;

class DeltaTimeExample
{
    static void Main(string[] args)
    {
        DateTime time1 = DateTime.Now;
        DateTime time2 = DateTime.Now;

        // Here we find DeltaTime in while loop
        while (true)
        {
            // This is it, use it where you want, it is time between
            // two iterations of while loop
            time2 = DateTime.Now;
            float deltaTime = (time2.Ticks - time1.Ticks) / 10000000f; 
            Console.WriteLine(deltaTime);  // *float* output {0,2493331}
            Console.WriteLine(time2.Ticks - time1.Ticks); // *int* output {2493331}
            time1 = time2;
        }
    }
}

【讨论】:

    【解决方案3】:
    class Program
    {
        
        static double DeltaTime;
        static double Secondframe;
        static double Counter;
        static void Main(string[] args)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
           
            while (true)
            {
                TimeSpan ts = stopWatch.Elapsed;
                double FirstFrame = ts.TotalMilliseconds;
                
                DeltaTime = FirstFrame - Secondframe;
                
               
                Counter += DeltaTime;
                Console.WriteLine(Counter);
    
                Secondframe = ts.TotalMilliseconds;
            }
         }
      }
    

    }

    【讨论】:

    • 请解释一下您的解决方案的作用
    【解决方案4】:

    DeltaTime 类帮助您实现动画。

     public class DeltaTime
            {
                DateTime FirstTime;
                public static DeltaTimer CreatePoint()
                {
                    return new DeltaTime(){ FirstTime = DateTime.Now};
                }
                public  TimeSpan GetDeltaTime()
                {
        
                    if (FirstTime != null)
                    {
                        
                        return DateTime.Now - FirstTime;
                    }
                    return TimeSpan.FromSeconds(1/60); //If null then return 60 FPS.
                }
            }
    

    示例 1:

    public async void TEST1_Animation(Button button)
            {
                var pointer=  DeltaTime.CreatePoint();
                for(double h = 0; h<button.Height;h++)
                {
                     var n= pointer.GetDeltaTime().TotalSeconds;
                    h = h * n;
                    await button.Dispatcher.InvokeAsync(() => { button.Height= h; });
                    await Task.Delay(TimeSpan.FromSeconds(1 / 60 * n));
    
                }
            }
    

    您的代码将如下所示:

    static void Update()
        {
            var Pointer = DeltaTimer.CreatePoint();
           
            while (true)
            {
                pSim.Update(Pointer.GetDeltaTime().TotalMilliseconds);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多