C# 如何从不断变化的对象列表中获取组件?

C# 如何从不断变化的对象列表中获取组件?,c#,list,unity3d,unity5,C#,List,Unity3d,Unity5,在unity的3d无止境跑步者游戏中,我遇到了这个问题。我有一个在玩家沿z方向运行时放置在玩家面前的平台段/道路列表。我下载了一个名为Dreamteck样条线的新资产包。因此,每个平台都有一个连接到它的样条线组件。铺设平台后,玩家抓住样条线并按照样条线的模式运行 假设玩家在第一个平台上。当播放器到达第一个平台的样条曲线的末端时,将调用OnEndReached事件处理程序,该处理程序基本上表示当到达样条曲线的端点时希望发生什么。所以我想知道,一旦到达终点,如何得到下一条样条曲线 p=球员 如上图所

在unity的3d无止境跑步者游戏中,我遇到了这个问题。我有一个在玩家沿z方向运行时放置在玩家面前的平台段/道路列表。我下载了一个名为Dreamteck样条线的新资产包。因此,每个平台都有一个连接到它的样条线组件。铺设平台后,玩家抓住样条线并按照样条线的模式运行

假设玩家在第一个平台上。当播放器到达第一个平台的样条曲线的末端时,将调用OnEndReached事件处理程序,该处理程序基本上表示当到达样条曲线的端点时希望发生什么。所以我想知道,一旦到达终点,如何得到下一条样条曲线

p=球员

如上图所示,这就是我试图实现的目标。作为平台铺设方式的简要说明,一旦玩家走到下一条路,他刚刚通过的那条路就会被禁用,因此下次他可以在玩家面前随机重复使用这条路

代码:跟踪管理器脚本。 公共部分[]tilePrefabs; 公共静态段新闻段

    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;
    }

目前我使用碰撞器,每条道路都有一个长方体碰撞器组件。一旦玩家到达平台的末端,它就会得到下一个样条线组件。它可以工作,但有时它无法识别下一条样条线并使用相同的样条线,这会导致玩家一次又一次地运行他经过的相同平台


所以我没有主意了。所以我来这里寻求解决方案或建议。非常感谢您的帮助。

如果您使用的是二维对撞机,请使用OnTiggerEnter或OnTiggerEnter2D。但正如你所说,你已经在使用对撞机,我想这是你已经尝试过的

你可以试试:

安提格尔斯泰尔酒店

向下投射到地面对象的光线。此链接中有一个二维示例:

也可以使用三维对象进行光线投射

在这种情况下,你使用它的目的基本上是向你的玩家下方的地面发射一束激光,然后根据你告诉它要击中的层次抓取一个物体。所以,如果你有一个叫做地面的层,你的平台就是其中的一部分,那么它只能从该层返回对象


只要记住经常进行光线投射,它就会更新以反映游戏。

在这种情况下,我只需将可能的片段存储在一个列表中,然后当我到达末尾时,获取下一个片段,并将当前第一个片段移动到末尾,或者移动到列表中任何您想要移动的位置

就是

public Segment currentSegment;
public List<Segment> segments;
void OnEndReached()
{
    //Put the completed segmetn back in the list ... probably at the end or randomized anywhere but at the start
    segments.Insert(segments.Count-1, currentSegment);
    //Now get the next segment
    currentSegment = segments[0];
    segments.RemoveAt(0);
}

请注意,我从列表中删除了我所在的片段。。。该列表仅代表即将到来的顺序,在跑步者游戏中,我发现知道这一点很方便,例如,我可以重置内容,根据性能、分数等更改分段的属性。

您是否愿意显示表示上述内容的代码?如果没有它,我们就看不到你实际上在做什么。它是有效的,但有时它失败了,这不适合解释这个问题。因为您的解决方案中可能没有代码,所以您不太可能提供。。。因此,这个问题很可能不适合这样做-如果你能用实际的代码/任何演示问题的东西发布,那就好了,否则,考虑删除和寻找统一的论坛,以发布您的问题将更好,所以问答网站,不适合讨论一个问题的可能的方法,我不知道SpulnServ.OnEnDead事件是在哪里,你能张贴相关的代码?@ GALANDIL它是一个事件处理程序。脚本在我购买的资产包中。这部分代码是有效的。我只想在玩家到达样条线末端时,以不同的方式获取下一个样条线组件。基本上如图所示,玩家到达当前平台或道路末端后,我如何获取任何组件。嗨。它是3d的。我的错误。我应该添加代码。不过你应该试试光线投射。但是它会影响你的表现吗?我怀疑它会对你的表现产生任何影响。除非您同时将其添加到许多不同的对象中。但只要你在一个玩家或几个物体上使用它就可以了。好的,我会试试。谢谢如果这行得通的话。我会打标记作为答案。记住使用3D物理,而不是2D,因为你在3D中工作。非常感谢。这帮助我完成了它D
segments.Insert(UnityEngine.Random.Range(1, segments.Count), currentSegment);