我在Unity Answers上发布了这个问题,到目前为止还算不上运气,所以我想我也可以在这里回答。
我正在从事一个涉及AI代理的项目,该项目要接受培训以在环境中导航,并且我想可视化随着培训的进行而变化的运动方式。我从使用内置组件TrailRenderer开始,但是包含跳转(从当前培训课程结束到开始位置的跳转)使我很烦,所以我编写了自己的自定义实现。
我希望自己的实现具有三种能力;可以限制可见的痕迹的数量,可以根据它们的相关性更改绘制的痕迹的alpha值,并且不包括跳转(如使用TrailRenderer组件时一样)。
下面显示并详细说明了实现,但是我认为在深入探讨实现之前概述最大的障碍是有意义的。
如我所见,目前我自己实现过程中最大的麻烦是,某些线索可能最终由大量的点组成(到目前为止,见证人的最大点数为30000+),如果环境足够具有挑战性,这极大地减慢了培训速度。除了增加时间延迟,使新点仅每0.5秒增加一次,我不知道该如何改善。但是,较大的时间延迟会导致可视化路径的准确性更高,从而限制了路径提供的价值。
在我的机器上,进行训练(500000步)(不计画线)大约需要45分钟。通过实施绘制轨迹和0.5秒的时间延迟,220000个训练步骤大约需要1.5个小时,之后我决定停止训练。
我的实现包括两个部分;附加到代理的脚本,该脚本绘制当前路径,并可能增加时间延迟。第二部分不是脚本本身,而是AgentReset()方法的一部分,它有两个作用;在运行时添加/删除路径,并根据其相关性更改路径的Alpha,即最新路径的Alpha值最高。
下面是附加到代理的脚本,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class drawDynamicTrail : MonoBehaviour
{
private GameObject[] trails;
private int traceStep = 0;
private int traceNumber = 0;
private int currentTrace;
private LineRenderer lr;
private float timeToDraw = 0;
public bool drawTrails = false;
void Update()
{
if (drawTrails){
if (Time.time > timeToDraw)
{
trails = GameObject.FindGameObjectsWithTag("Trail");
if (trails.Length != traceNumber)
{
traceNumber = trails.Length;
traceStep = 0;
} else
{
currentTrace = traceNumber - 1;
lr = trails[currentTrace].GetComponent<LineRenderer>();
if (traceStep >= lr.positionCount)
{
lr.positionCount = traceStep + 1;
}
lr.SetPosition(traceStep,transform.position);
traceStep += 1;
}
timeToDraw = Time.time + 0.5f;
}
}
}
}
我很乐意在需要时提供整个AgentReset()方法,但由于我相信这并不是挑战的源头,因此暂时不提供。
所有建议都受到高度赞赏。
答案 0 :(得分:1)
一般性能提示:尽可能避免在“更新”中使用“ FindGameobject ...”。在您的情况下,我认为线索列表正在增长,因此您需要对其进行更新,对吗?
想法:
公开SELECT * FROM sb
ORDER BY LENGTH(id) DESC, id DESC
或定义trails
方法-每当创建新的带有“ Trail”标签的对象时,都添加跟踪。这应该更快,因为“ FindGameobject ...”将花费越来越长的时间,场景中的对象越多。
您真的对所有路径感兴趣吗?还是最新的就足够了?如果您只想绘制最新的踪迹,请考虑新的Ringbuffer mode
旧路不会改变吗?相机会移动吗?如果不是,则可以在纹理中绘制这些路径,因此您只需在旧路径上方绘制新路径,而无需重新绘制旧路径。除了重新绘制纹理。但这是内存恒定。