【问题标题】:Child object transform position,rotation,scale incorrect away from origin?子对象变换位置,旋转,比例远离原点不正确?
【发布时间】:2019-04-29 16:05:38
【问题描述】:

我们有一个父对象,我们称它为RectangleParent,我们希望将子对象,在我们的例子中为Squares,(在运行时确定的总数在1-10 的范围内)在这个表面中。两者都在我们的父对象 RectangleParent 的边界内,彼此均匀分布,从左到右最多两行(每行最多 5 个项目,最多两行,等于最多 10 个 sqaures)。

开始编辑

结束编辑

示例 Unity pkg here

正确示例:

十 (10) 个要放置的对象

五 (5) 个 放置对象

当前结果

注意我们在原点的父对象(父对象是细长的矩形,子对象是较小的正方形)。它的孩子可以根据需要放置,满足所有要求。放置在父边界内,两行在其父边界内彼此均匀间隔,并且每个子对象彼此间隔均匀。如十 (10) 个对象示例所示。

但是请注意,对于不位于原点的父对象 - 未放置在其父边界内的子对象(正方形),两行之间的间距不适合父边界,并且对象不再是正方形(它们现在看起来像矩形)。然而,每一行中的子对象之间的间隔是均匀的,因此这里至少满足了一个愿望。

如果我们分配Cube.transform .localPosition 而不是.position

原产地: 行之间的间距仍然正确,但现在每行内的子对象(正方形)之间的间距不正确,并且所有子对象都未保持在其父对象范围内。

远离原点: 两行对齐正确,但两行间距不正确。这两行不适合其父对象边界。子对象本身有多个问题。它们不是正方形,彼此之间的间距不正确。

那么我们的 3D 放置数学有什么问题呢?如何固定我们的对象放置,以便无论我们的父对象在哪里,我们的子对象都被放置在其父对象的范围内?

代码

public class NewBehaviourScript : MonoBehaviour {

    public int NumberOfObjectsToPlace = 10;   //Place 10 objects
    public int maxRows = 5; // how many objects can be placed in a row
    public int maxColumns = 2; // how many objects can be placed in a column

    public GameObject RectangleParent;  //the parentObject instance
    public GameObject CubePrefab;       //the cube prefab

    // Use this for initialization
    void Start () {
        PlaceObjects();
    }

    // Update is called once per frame
    void Update () {

    }

    void PlaceObjects()
    {
        Vector3 center = RectangleParent.GetComponent<MeshRenderer>().bounds.center;
        Vector3 size = RectangleParent.GetComponent<MeshRenderer>().bounds.size;
        Vector3 corner = -new Vector3(size.x / 2, 0, size.z / 2);
        float stepX = size.x / (maxColumns + 1);
        float stepZ = size.z / (maxRows + 2);
        int placedObjects = NumberOfObjectsToPlace;

        for (int i = 0; i < placedObjects; i++)
        {
            GameObject Cube = Instantiate(CubePrefab);
            Cube.transform.parent = RectangleParent.transform;
            Cube.transform.localRotation = Quaternion.identity;
            Cube.transform.position = corner + new Vector3(stepX, 
                center.y + 0.15f, 
                stepZ * 1.5f + i * stepZ
            );

            if (i == maxRows - 1)
            {
                i -= maxRows;
                placedObjects -= maxRows;
                stepX += size.x / (maxColumns + 1);
            }
        }
    }

}

(感谢@Ali-Baba 的所有帮助)

【问题讨论】:

    标签: c# unity3d math 3d transform


    【解决方案1】:

    你必须使用RectangleParent的位置和方向像

    Cube.transform.position = RectangleParent.transform.position 
    
                              + corner.x * RectangleParent.transform.right 
                              + corner.y * RectangleParent.transform.up 
                              + corner.z * RectangleParent.transform.forward 
    
                              + stepX * RectangleParent.transform.right 
                              + (center.y + 0.15f) * RectangleParent.transform.up 
                              + (stepZ * 1.5f + i * stepZ) * RectangleParent.transform.forward;
    

    或者您应该使用localPosition。这里的问题可能是,如果RectangleParent 的比例不是1,1,1localPosition 的值可能会随之缩放,所以您可能想要这样做

    Cube.transform.localPosition = new Vector3(
                                       corner.x / RectangleParent.transform.localScale.x, 
                                       corner.y / RectangleParent.transform.localScale.y, 
                                       corner.z / RectangleParent.transform.localScale.z)
    
                                   + new Vector3(
                                       stepX / RectangleParent.transform.localScale.x, 
                                       center.y + 0.15f, 
                                       (stepZ * 1.5f + i * stepZ) / RectangleParent.transform.localScale.z
                                   );
    

    然后为了正确重置比例,您可能想要这样做

    Cube.transform.localScale = new Vector3(
                                    1 / RectangleParent.transform.localScale.x, 
                                    1 / RectangleParent.transform.localScale.y, 
                                    1 / RectangleParent.transform.localScale.z
                                );
    

    使用

    private void PlaceObjects()
    {
        var center = RectangleParent.GetComponent<MeshRenderer>().bounds.center;
        var size = RectangleParent.GetComponent<MeshRenderer>().bounds.size;
        var corner = -new Vector3(size.x / 2, 0, size.z / 2);
        var stepX = size.x / (maxColumns + 1);
        var stepZ = size.z / (maxRows + 2);
        var placedObjects = NumberOfObjectsToPlace;
    
        for (var i = 0; i < placedObjects; i++)
        {
            var cube = Instantiate(CubePrefab);
    
            cube.transform.parent = RectangleParent.transform;
            cube.transform.localRotation = Quaternion.identity;
    
            cube.transform.localPosition = new Vector3(
                                               corner.x / RectangleParent.transform.localScale.x,
                                               corner.y / RectangleParent.transform.localScale.y,
                                               corner.z / RectangleParent.transform.localScale.z
                                           )
    
                                           + new Vector3(
                                               stepX / RectangleParent.transform.localScale.x,
                                               center.y + 0.15f,
                                               (stepZ * 1.5f + i * stepZ) / RectangleParent.transform.localScale.z
                                           );
    
            cube.transform.localScale = new Vector3(
                                            1 / RectangleParent.transform.localScale.x,
                                            1 / RectangleParent.transform.localScale.y,
                                            1 / RectangleParent.transform.localScale.z
                                        );
    
            if (i != maxRows - 1) continue;
    
            i -= maxRows;
            placedObjects -= maxRows;
            stepX += size.x / (maxColumns + 1);
        }
    }
    

    【讨论】:

    • 这看起来差不多了!请参阅添加到操作的视觉对象。这是在分配 localPosition 时修复子级之间的空间,但这两行仍然超出其父级的范围(使用您的替代解决方案)
    • 我不知道你到底是什么意思..它对我有用,请参阅添加的 gif。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多