此问题已经过编辑,可以提供尽可能多的有关问题的信息,正如有人建议我应该做的那样。现在有了它的赏金 - 这似乎是正确的事情。祝你好运,人们!
不要忘记,如果您觉得我没有包含任何内容,您可以随时提出其他问题!
我正在研究一个程序生成地形的系统,因为角色会使用各种不同的噪音走来走去 - 主要是perlin-和simplex-noise。世界本身有三个维度,虽然它在游戏中被视为top-down in two dimensions。
对于那些习惯于在程序上生成地形的人,您将意识到必须使用多线程才能在渲染器线程中不引起滞后尖峰。这正是我一直在尝试做的事情,在LibGDX的AsyncExecutor
以及相同的库AsyncTask
的帮助下,这是一个在提供的线程上运行的任务由AsyncExecutor
。
我的问题是AsyncExecutor
似乎根本不是异步的。它会在我的渲染器线程中引起滞后尖峰,理论上它可以使用渲染器线程也使用的资源。然而,事情是,渲染器线程以新的“块”生成 - 我称之为区域 - AsyncExecutor
然后处理。在AsyncExecutor
完全生成之前,不允许呈现器线程呈现该资源。
RegionHandler
我有一个名为RegionHandler
的班级,它将新区域放置在玩家移动的方向,并从相反的方向移除区域 - 以便程序不必知道超过13 x 9个区域一次。
以下是一段简短的代码,解释了它的工作原理 - 评论是否有简化讨论代码的不同部分:
// These ‘if’s are triggered when the player moves
// to a certain position
if(addLeft)
{
// Adds new regions to the left and removes to the right
// ...
// Submit ‘RegionLoader’ task to ‘asyncExecutor’
// with regions that needs be generated as well as ‘toSends’ which is
// also part of that generation
asyncExecutor.submit(new RegionLoader(toGenRegions, toSends));
}
else if(addRight)
{
// Adds new regions to the right and removes to the left
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toGenRegions, toSends));
}
if(addBottom)
{
// Adds new regions to the bottom and removes to the top
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toSend, toSends));
}
else if(addTop)
{
// Adds new regions to the top and removes from the bottom
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toSend, toSends));
}
asyncExecutor
实际上是AsyncExecutor
而RegionLoader
实现了AsyncTask
界面。我已经测试了这段代码需要多长时间才能完成 - 这段代码永远不会花费一毫秒的时间来运行。
Region
在列表中处理:
List<List<Region>> regions;
RegionLoader
此类是一项能够由AsyncExecutor
运行的任务。
private class RegionLoader implements AsyncTask<Object>
{
private List<Region> regions;
private List<ToSendInner> toSends;
public RegionLoader(
List<Region> regions,
List<ToSendInner> toSends)
{
this.regions = regions;
this.toSends = toSends;
}
@Override
public Object call() throws Exception
{
// Generates the ‘Region’s it has been given inside the constructor
// ...
return null;
}
}
call()
完成后,它会将boolean
设置为true
,以便呈现该特定Region
。
虽然AsyncExecutor
是异步的,但它会在渲染器线程内每隔一段时间引起一次滞后尖峰。如前所述,这可能是由AsyncExecutor
使用与渲染器线程相同的资源引起的,但渲染器线程仅在允许的情况下呈现Region
- 因此我无法看到为什么会导致滞后峰值。
我尝试过使用常规Java线程,但I read somewhere由于支持Android开发的 LibGDX 而可能无法正常工作,Android在多线程方面没有相同的功能 - 但我真的错了!
也许有人在他们的游戏开发职业中遇到过类似的问题?如果是这样,也许有人可以指出我正确的方向?
答案 0 :(得分:1)
我将查看垃圾收集的效果,因为您似乎正在将新的Region对象传递给任务。请尝试重新使用/重新填充现有区域。
答案 1 :(得分:0)
我不记得有关Android和线程的任何问题并搜索但没有找到任何内容。你应该测试一下。
我将假设生成区域与openGL无关。所以你不必在主线程上运行它。
试试这个:主题+ Gdx.app.postRunnable()
new Thread(new Runnable() {
Variables...
public Runnable set(Variables... ) {
// set variables
return this;
}
@Override
public void run() {
// do stuff
Gdx.app.postRunnable(() -> {
// commit that stuff.
});
}
}.set(regions,whateverelse)).start();
如果你看一下AsyncExecutor的源代码,你会发现它完全一样。但只有它不会让第二个runnable同时运行。
注意: AsyncExecutor的实现更改为在gwt后端立即执行。由于我猜的限制。你可能不应该以gwt为目标。
试试吧,让我知道。如果主线程仍然挂起,那是因为你在 //提交那些东西部分正在做什么。发布更多代码,还不足以理解问题的根源。
编辑:还可以使用Gdx.graphics.getDeltaTime()查看是否真的挂起。它可能是由其他东西引起的,所以要消除其他可能性,并找出真正的原因是否是这项任务。