【问题标题】:Generate Sphere of Cubes生成立方体球体
【发布时间】:2019-05-13 19:09:30
【问题描述】:

我试图通过实例化立方体来生成一个球体。对于初学者来说,这听起来很容易——当然,我是在讽刺——但我在https://docs.unity3d.com/Manual/InstantiatingPrefabs.html 找到了一个例子——只不过它只是一个圆圈:

理想情况下,我希望生成器/代码也将立方体转换为并排放置(没有间距;或可配置间距),并具有多行,以便它们形成一个实心球体。所以我认为代码需要同时转换立方体的外表面和内表面。

如何做到这一点?这是圆圈的代码:

using UnityEngine;
public class CubeSphere : MonoBehaviour {
    // Instantiates prefabs in a circle formation
    public GameObject prefab;
    public int numberOfObjects = 4;
    public float radius = 5f;
    void Start() {
        for (int i = 0; i < numberOfObjects; i++) {
            float angle = i * Mathf.PI * 2 / numberOfObjects;
            float x = Mathf.Cos(angle) * radius;
            float z = Mathf.Sin(angle) * radius;
            Vector3 pos = transform.position + new Vector3(x, 0, z);
            float angleDegrees = -angle * Mathf.Rad2Deg;
            Quaternion rot = Quaternion.Euler(0, angleDegrees, 0);
            Instantiate(prefab, pos, rot);
        }
    }
}

额外问题:是否也可以弯曲预制件(如曲面屏幕),从而得到一个非常光滑的预制件球体?

【问题讨论】:

    标签: c# visual-studio unity3d 3d


    【解决方案1】:

    定义一个点 (Vector3) 作为中心。让我们调用 c

    将距离(浮点数)定义为半径的长度。称它为 R

    想象一条通过 c 长度为 2R 的垂直线:

    | \
    |  )R
    | /
    c
    | \
    |  )R
    | /
    

    一个球体只不过是许多圆周,一个在另一个之下:

          --|--        circunference 1
       -----|-----     circunference 2
     -------|-------   circunference 3
    --------c--------  circunference 4
     -------|-------   circunference 5
       -----|-----     circunference 6
          --|--        circunference 7
    

    现在你需要定义你想要在你的球体中有多少个圆周,你拥有的越多,它看起来就越好(也就越重)。在这个例子中,我们使用了 7 个循环。我们应该有它们每个的位​​置(在 y 轴上),这很容易评估。

    如何评估这些圆周的半径?让我们看一个评估圆周 1 半径的示例:

         .--|--                     .--|     by definition, we have this
       ---\-|-----                  |\ | h   height h (it is not c.y + R, 
     ------\|-------                | \|     is something below that)
    --------c--------  =>           '--c    
     -------|-------                 x
       -----|-----     
          --|--        
    

    我们知道cos(angle) = h / R,因此我们将角度评估为angle = arccos(h / R)

    半径x应该是R * sin(angle)


    最后一步是决定你应该在每个循环中实例化多少个立方体。您可以根据圆周的长度(2πr)来决定。你可以假设对于某个长度 L,会有一个立方体,所以对于任何长度 2πr,应该有 2πr/L 个立方体。您可以轻松评估每个立方体的位置:

    假设圆周 1 的半径为 r,2πr/L = 3,所以我们将有 3 个立方体:

     ^         _.----[2]                 ^
     |       .'         '.               |          [][][]    circunference 1
     |      /             \              |        [][][][][]
    z|    [1]      c       |            y|      [][][][][][][]     ...
     |      \             /              |        [][][][][]
     |       '.         .'               |          [][][]    curcunference 7
     |         ''----[3]                 |
     |---------------------------->      |---------------------------->
                   x                                  x
    

    显然,您定义的 L 越小,立方体就越多,外观也会越好。

    【讨论】:

    • 谢谢!这肯定会帮助我朝着正确的方向前进!
    【解决方案2】:

    从 youtube 上的一个教程中找到了一个脚本。

    脚本:VoxelTools.cs

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class VoxelTools : MonoBehaviour
    {
    
        private static GameObject cubePrefab;
        private static GameObject cubeContainer;
        private static int cubeCount = 0;
        private static List<GameObject> cubes;
    
        public static Color GetRandomColor()
        {
            float r = Random.Range(0f, 1f);
            float g = Random.Range(0f, 1f);
            float b = Random.Range(0f, 1f);
    
            //make grey/sludge colors less likely
            for (int i = 0; i < Random.Range(1, 3); i++)
                {
                if (Random.Range(0, 10) > 1)
                {
                    int a = Random.Range(0, 3);
                    if (a == 0)
                        r = 0;
                    if (a == 1)
                        g = 0;
                    if (a == 2)
                        b = 0;
                }
            }
    
            return new Color(r, g, b);
        }
    
        public static GameObject MakeCube(float x, float y, float z)
        {
            return MakeCube(x, y, z, Color.red, 1);
        }
    
        public static GameObject MakeCube(float x, float y, float z, Color color)
        {
            return MakeCube(x, y, z, color, 1);
        }
    
        public static GameObject MakeCube(float x, float y, float z, Color color, float size)
        {
            return MakeCube(new Vector3(x, y, z), color, size);
        }
    
        private static GameObject GetCubePrefab()
        {    
            if (cubePrefab == null)
                cubePrefab = Resources.Load("Cube") as GameObject;
            return cubePrefab;
        }
    
    public static GameObject MakeCube(Vector3 position, Color color, float size)
    {
        cubeCount++;
        if (cubeContainer == null)
        {
            cubeContainer = new GameObject("cube container");
            cubes = new List<GameObject>();
        }
    
        GameObject cube = Instantiate(GetCubePrefab()) as GameObject;
        cubes.Add(cube);
        cube.transform.position = position;
        cube.transform.parent = cubeContainer.transform;
        cube.name = "cube " + cubeCount;
    
        cube.GetComponent<Renderer>().material.color = color;
        cube.transform.localScale = new Vector3(size, size, size);
    
        return cube;
    }
    
        public static void MakeAllCubesFall()
        {
            foreach (GameObject cube in cubes)
                if (cube.GetComponent<Rigidbody>() == null)
                    cube.AddComponent<Rigidbody>();
        }
    }
    

    结果:

    如果有帮助,请告诉我。

    【讨论】:

    • 谢谢!但是不应该有一个 Start() 方法(或某种)来进行实际布局吗?我似乎无法在其中找到数学部分...
    • youtube.com/watch?v=NUMYRgwOmO8 这里是源视频。导师学分:codingplayground.ca
    • VoxelTools.cs 不是制作这个的脚本,它只是一个处理立方体生成的辅助类。看我的回答。
    【解决方案3】:

    使用其他答案中提供的 VoxelTools.cs:

    public void CreateSphere(int r, Vector3 center) {
        int r2 = r*r;
        for (int x = -r; x <= r; ++x)
            for (int y = -r; y <= r; ++y)
                for (int z = -r; z <= r; ++z)
                    if (new Vector3(x,y,z).sqrMagnitude <= r2)
                        VoxelTools.MakeCube(center.x + x, center.y + y, center.z +z);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-25
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      • 2019-11-29
      相关资源
      最近更新 更多