【发布时间】:2018-02-16 16:54:45
【问题描述】:
在一个 3d 无尽的跑步游戏中工作时,我遇到了这个问题。我有一个平台列表(路段/道路),当玩家在 z 方向运行时,这些平台位于玩家面前。我已经下载了一个名为 Dreamteck splines 的新资产包。所以每个平台都有一个附加的样条组件。放置平台后,玩家抓住样条线并按照样条线的模式运行。
假设玩家在第一个平台上。当玩家到达第一个平台样条线的末端时,OnEndReached() 事件处理程序被调用,它基本上说明了当到达样条线的端点时您想要发生的事情。所以我想知道到达终点后如何获得下一条样条线。
P = 玩家
如上图所示,这就是我想要完成的任务。作为对如何铺设平台的简要说明,一旦玩家进入下一条道路,他刚刚经过的道路就会被禁用,因此下次他可以随机重用玩家面前的道路。
代码:轨道管理器脚本。 公共段[] tilePrefabs; public static Segment newSegment;
public static List<Segment> m_Segments;
public static List<Segment> m_PastSegements;
private int m_SafeSegmentLeft;
private int m_PreSegments = -1;
private float startingSegmentDistance = 4f;
private int startingSafeSegments = 2;
private int amtSegmentsOnScreen = 10;
private float segmentRemovalDistace = -40f;
private float m_TotalWorldDistance;
private float m_CurrentSegmentDistance;
void Update ()
{
while (m_Segments.Count < amtSegmentsOnScreen)
{
SpawnNewSegment();
}
m_TotalWorldDistance += scaledSpeed;
m_CurrentSegmentDistance += scaledSpeed;
if (m_CurrentSegmentDistance > m_Segments[0].worldLength)
{
m_CurrentSegmentDistance -= m_Segments[0].worldLength;
m_PastSegements.Add(m_Segments[0]);
m_Segments.RemoveAt(0);
}
Vector3 currentPos;
Quaternion currentRot;
Transform playerTransform = playerMotor.transform;
m_Segments[0].GetPointAtInWorldUnit(m_CurrentSegmentDistance, out currentPos, out currentRot);
bool needRecenter = currentPos.sqrMagnitude > floatingOriginThreshold;
if (needRecenter)
{
int count = m_Segments.Count;
for (int i = 0; i < count; i++)
{
m_Segments[i].transform.position -= currentPos;
}
count = m_PastSegements.Count;
for (int i = 0; i < count; i++)
{
m_PastSegements[i].transform.position -= currentPos;
}
m_Segments[0].GetPointAtInWorldUnit(m_CurrentSegmentDistance, out currentPos, out currentRot);
}
playerTransform.rotation = currentRot;
playerTransform.position = currentPos;
for (int i = 0; i < m_PastSegements.Count; i++)
{
if ((m_PastSegements[i].transform.position - currentPos).z < segmentRemovalDistace)
{
m_PastSegements[i].Cleanup();
m_PastSegements.RemoveAt(i);
i--;
}
}
}
public void SpawnNewSegment()
{
int useSegment = Random.Range(0, tilePrefabs.Length);
if (useSegment == m_PreSegments)
{
useSegment = (useSegment + 1) % tilePrefabs.Length;
}
Segment segmentToUse = tilePrefabs[useSegment];
newSegment = Instantiate(segmentToUse, Vector3.zero, Quaternion.identity);
Vector3 currentExitPoint;
Quaternion currentExitRotation;
if (m_Segments.Count > 0)
m_Segments[m_Segments.Count - 1].GetPointAt(1.0f, out currentExitPoint, out currentExitRotation);
else
{
currentExitPoint = transform.position;
currentExitRotation = transform.rotation;
}
newSegment.transform.rotation = currentExitRotation;
Vector3 entryPoint;
Quaternion entryRotation;
newSegment.GetPointAt(0.0f, out entryPoint, out entryRotation);
Vector3 pos = currentExitPoint + (newSegment.transform.position - entryPoint);
newSegment.transform.position = pos;
newSegment.manager = this;
newSegment.transform.localScale = new Vector3((Random.value > 0.5f ? -1 : 1), 1, 1);
newSegment.objectRoot.localScale = new Vector3(1.0f / newSegment.transform.localScale.x, 1, 1);
if (m_SafeSegmentLeft <= 0)
SpawnObstacle(newSegment);
else
m_SafeSegmentLeft -= 1;
m_Segments.Add(newSegment);
}
播放器脚本
//Current tile segment;
private Segment currentSegment;
//Spline Follower
private SplineFollower follower
//For Dreamteck spline -->
private Segment nextSegment;
void Start()
{
playerCollider = GetComponent<CapsuleCollider>();
anim = GetComponent<Animator>();
follower = GetComponent<SplineFollower>();
moveLane = currentLane;
follower.onEndReached += Follower_onEndReached;
}
private void Follower_onEndReached()
{
currentSegment = nextSegment;
follower.computer = currentSegment.spline;
}
void OnTriggerEnter(Collider col)
{
nextSegment = col.GetComponentInParent<Segment>();
}
路段脚本:附加到每条道路/平台
public SplineComputer spline;
public static Segment next;
SplinePoint[] points;
void Start()
{
spline = GetComponentInChildren<SplineComputer>();
spline.space = SplineComputer.Space.Local;
points = spline.GetPoints();
if (points.Length == 0)
return;
}
在我使用碰撞器的那一刻,每条道路都有一个盒子碰撞器组件。一旦玩家到达平台的末端,它就会得到下一个样条线组件。它可以工作,但有时它无法识别下一个样条线并使用相同的样条线,这导致玩家一次又一次地运行他经过的同一个平台。
所以我没有想法。所以来这里寻找解决方案或建议。帮助将不胜感激。
【问题讨论】:
-
您愿意展示代表您上面描述的代码吗?没有它,我们就看不到你实际在做什么。
-
“它可以工作,但有时它会失败”不是对 SO 问题的合适解释。由于您的解决方案中可能没有代码,因此您不太可能提供minimal reproducible example...因此,该问题可能不适合SO-如果您可以edit 发布实际代码/任何演示问题就好了,否则考虑删除并在 Unity 上寻找 论坛 来发布您的问题会更好(SO 是问答网站,不适合讨论解决问题的可能方法)
-
我没有看到
SplineFollower.onEndReached事件是在哪里引发的,你能发布相关代码吗? -
@Galandil 这是一个事件处理程序。该脚本在我购买的资产包中。这部分代码有效。一旦玩家到达样条线的末端,我只想要一种不同的方式来获取下一个样条线组件。基本上如图所示,一旦玩家到达当前平台或道路的末端,我如何获取任何组件。