从左到右读取对象

Posted

技术标签:

【中文标题】从左到右读取对象【英文标题】:Read objects from left to right 【发布时间】:2018-01-03 14:11:18 【问题描述】:

我在 Unity 中编写了一个 C# 脚本,它可以检测所有可见对象。现在我想从左到右输出它们,就像它们在场景中的位置一样。每个对象都有一个数字,但脚本按升序输出对象。

我的想法:

我想到了一个沿着水平视野的for-loop。首先计算水平FOV:

private static float horizontalFOV() 
    float radAngle = Camera.main.fieldOfView * Mathf.Deg2Rad;
    float radHFOV = 2 * Mathf.Atan(Mathf.Tan(radAngle / 2) * Camera.main.aspect);
    float hFOV = Mathf.Rad2Deg * radHFOV;

    return hFOV;

并通过以下方式创建循环:

public static string OutputVisibleRenderers (List<Renderer> renderers) 
    float hFov = horizontalFOV ();

    if (null == renderers)
        throw new System.ArgumentNullException ("renderers are null");

    for (int i = 0; i < hFov; i++) 
        foreach (var renderer in renderers) 
                if (IsVisible (renderer)) 
                myList.Add (renderer.name);
            
        
    
    string itemsInOneLine = string.Join ("-", myList.ToArray());
    myList.Clear ();
    print (itemsInOneLine);
    print ("--------------------------------------------------");
    return itemsInOneLine;

但不幸的是,这不起作用。那么我怎么能从左到右读取所有对象呢?

【问题讨论】:

您是否遇到错误或renderers 为空,或者他们没有被添加到列表中? 更多关于它如何“不起作用”的信息会有所帮助。 对不起,我的意思是创建了列表,但所有名称(都是数字)都是按升序添加的。我希望它们按“位置”顺序从左到右添加。 你需要对它们进行排序,你可以使用每个对象的transform.position作为排序的值。 @Draco18s 我怎么能意识到? 【参考方案1】:

我不使用 Unity,如果我遗漏了什么,很抱歉,但似乎虽然在外部 for 循环中您从左到右查看,但您没有在循环内使用此信息。内部循环只是检查每个渲染器是否可见并将其添加到列表中,因此它们可能会按照它们在 renderers 集合中的放置顺序出现在输出列表中。

为了从左到右对对象进行排序,您可能应该计算它们在屏幕上的坐标,然后使用它们进行排序。要计算这个,您可以使用Camera.WorldToScreenPoint 方法。我在这里找到了一些可能有用的建议:http://answers.unity3d.com/questions/49943/is-there-an-easy-way-to-get-on-screen-render-size.html

要对对象进行排序,您可以使用此处描述的SortedList 类:https://msdn.microsoft.com/en-us/library/ms132319(v=vs.110).aspx。 计算出每个对象的屏幕坐标后,只需将其添加到以屏幕X坐标为键的列表中,列表将自动保持对象的有序。

【讨论】:

我不确定你的意思。请解释为什么Bound 在这种情况下不是静态的是一个问题。【参考方案2】:

假设renderers 是一个List,你可以使用List.Sort 方法并使用点积将对象从左到右排序。

我已经制作了一个可以在这里使用的脚本,试试看

    public System.Collections.Generic.List<Renderer> renderers ;

    private void Start()
    
        var sortedRenderers = new System.Collections.Generic.List<Renderer>( renderers ) ;
        sortedRenderers.Sort( SortLeftToRight ) ;

        for( int i = 0 ; i < sortedRenderers.Count ; ++i )
            Debug.Log( sortedRenderers[i].name ) ;

    
    private int SortLeftToRight( Renderer r1, Renderer r2 )
    
        Transform camTransform = Camera.main.GetComponent<Transform>(); // You can optimize if you cache the transform of the camera
        Vector3 axis = camTransform.right ; 
        Transform t1 = r1.gameObject.GetComponent<Transform>();
        Transform t2 = r2.gameObject.GetComponent<Transform>();
        float dot1 = Vector3.Dot( axis, t1.position - camTransform.position );
        float dot2 = Vector3.Dot( axis, t2.position - camTransform.position );

        if( Mathf.Abs( dot1 - dot2 ) < 0.001f )
            return 0 ;

        return dot1 < dot2 ? -1 : 1 ;
    

有用的链接:

https://msdn.microsoft.com/fr-fr/library/w56d4y5z(v=vs.110).aspx https://docs.unity3d.com/Manual/UnderstandingVectorArithmetic.html

【讨论】:

在我的代码中,我不检查渲染器是否可见。检查此问题以过滤渲染器是否可见:***.com/questions/26196/…

以上是关于从左到右读取对象的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 从左到右读取多行

如何让 div 的内容从左到右,然后 drop e 继续从左到右

jQuery FadeIn 从左到右

UIImageView从左到右改变动画

核心动画从左到右

从左到右平滑地重复动画