【问题标题】:How can I calculate and create positions of triangle shape?如何计算和创建三角形的位置?
【发布时间】:2018-11-05 21:34:21
【问题描述】:
private void FormationTriangle()
{
    newpositions = new List<Vector3>();
    for (int x = 0; x < squadMembers.Count; x++)
    {
        for (int y = x; y < 2 * (squadMembers.Count - x) - 1; y++)
        {
            Vector3 position = new Vector3(x, y);
            newpositions.Add(position);
        }
    }

    move = true;
    formation = Formation.Square;
}

循环错误。它将小队成员排成一排。 甚至不接近三角形。 我希望小队成员站成三角形。

这是移动部分:但问题在于循环计算三角形位置。我做的其他编队工作正常。

private void MoveToNextFormation()
{
    if (randomSpeed == false)
    {
        if (step.Length > 0)
            step[0] = moveSpeed * Time.deltaTime;
    }

    for (int i = 0; i < squadMembers.Count; i++)
    {
        squadMembers[i].transform.LookAt(newpositions[i]);
        if (randomSpeed == true)
        {
            squadMembers[i].transform.position = Vector3.MoveTowards(
                squadMembers[i].transform.position, newpositions[i], step[i]);
        }
        else
        {
            squadMembers[i].transform.position = Vector3.MoveTowards(
                squadMembers[i].transform.position, newpositions[i], step[0]);
        }
        if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) < 
            threshold)
        {
            if (squareFormation == true)
            {
                Vector3 degrees = new Vector3(0, 0, 0);
                Quaternion quaternion = Quaternion.Euler(degrees);
                squadMembers[i].transform.rotation = Quaternion.Slerp(
                    squadMembers[i].transform.rotation, quaternion, 
                    rotateSpeed * Time.deltaTime);
            }
            else
            {
                squadMembers[i].transform.rotation = Quaternion.Slerp(
                    squadMembers[i].transform.rotation, quaternions[i], 
                    rotateSpeed * Time.deltaTime);
            }
        }
    }
}

【问题讨论】:

  • 是不是因为newpositionssquadMembers 多?

标签: c# unity3d


【解决方案1】:

这个答案会产生一个这样排列的三角形:

    x
   x x
  x x x
 x x x x
x x x x x 

或者,如果不够填满一个完整的三角形:

    x
   x x
  x x x
 x x x x
x   x   x 

由于无法保证完美三角形的单位数量,因此您应该高估三角形的大小,计算已放置的单位数量,然后在达到限制时停止放置。

首先,find the height of the smallest triangular number greater than your number of units, and that triangular number itself

int height = Mathf.CeilToInt( (Mathf.Sqrt(8*squadMembers.Count+1f)-1f)/2 ) 
int slots = (int)(height * (height+1f)/2f)

然后,找到第一个单元的位置。我们需要知道how many rows 我们有多少个插槽以及最下面一行插槽的宽度:

float verticalModifier = 0.8f;  // 0.8f to decrease vertical space
float horizontalModifier = 1.25f; // 1.25f to increase horizontal space

float width = 0.5f * (height-1f);
Vector3 startPos = new Vector3(width* horizontalModifier, 0f, (float)(height-1f) * verticalModifier);

然后,添加,直到添加足够

int finalRowCount = height - slots + squadMembers.Count;
for (int rowNum = 0 ; rowNum < height && newpositions.Count < squadMembers.Count; rowNum++) {
    for (int i = 0 ; i < rowNum+1 && newpositions.Count < squadMembers.Count ; i++ ) {
        float xOffset = 0f;

        if (rowNum+1 == height) {
            // If we're in the last row, stretch it ...
            if (finalRowCount !=1) {
                // Unless there's only one item in the last row. 
                // If that's the case, leave it centered.

                xOffset = Mathf.Lerp(
                        rowNum/2f,
                        -rowNum/2f,
                        i/(finalRowCount-1f)
                        ) * horizontalModifier;
            }
        }
        else {
            xOffset = (i-rowNum /2f) * horizontalModifier; 
        }

        float yOffset = (float)rowNum * verticalModifier; 

        Vector3 position = new Vector3(
                startPos.x + xOffset, 0f, startPos.y - yOffset);
        newpositions.Add(position);

    }
}

【讨论】:

  • 三角形不准确。请查看链接中的此屏幕截图。从底部数第二个对象胶囊的最右排太靠外了,右排不像左排那样笔直。 imgur.com/a/9zOP3aj
  • 这是故意的。这不是一个三角形的单位数,所以它会组成另一行并尽可能多地填满它。
  • 我还有几个小时我会编辑这个以使底行一直展开。在我的手机上做不到。
  • 它的工作问题在于我为管理小队所做的其他脚本我使用滑块来控制小队的数量和每个小队的成员。并不是每个成员的数量都会形成一个准确的三角形,这也取决于我创建了多少个小队。我可以添加它的脚本,看看可以为它制作什么逻辑?这个想法是控制每个小队中的小队和成员的数量,然后从小队和成员中进行编队。现在我有3个阵型:正方形,圆形,三角形。我想知道它背后的逻辑应该是什么。
  • 也许您可以让滑块选择三角形的高度,并显示相应的三角形编号。 N = (h+1)*h/2。无论如何,我编辑了我的答案,现在最后一行展开了。如果后排只有一个,则到该行的中心。
【解决方案2】:

让我们看看位置列表包含的简单值n = 3

首先,将 x 从 0 循环到 2 (3 - 1) 然后对于每个 x,从 x 循环到 4-x (3*2 - x - 1 - 1)
记住 a&lt;ba&lt;=b-1 相同

这给了我们...

0,0
0,1
0,2
0,3
0,4
1,1
1,2
1,3
2,2

这是很多职位。当然可以住3个以上!至少它是一个三角形:

X\Y 0  1  2  3  4  
0   #  #  #  #  #  
1      #  #  #  
2         #  

主要问题是您生成的位置方式 比需要的多,并且期望以某种方式填补它。

您需要根据三角形的面积公式计算宽度和高度:A = (b*h)/2,您甚至可能需要b=h,其中A = number of units

所以,是这样的:

int b = Mathf.CeilToInt(Mathf.Sqrt(squadMembers.Count));
    for (int x = 0; x < b; x++)
    {
        //the divide by 2 is accounted for with this 2*
        for (int y = x; y < 2 * (b - x) - 1; y++)
        {
            Vector3 position = new Vector3(x, y);
            newpositions.Add(position);
        }
    }

【讨论】:

  • 在小队成员中有 20 名成员,但在循环之后,新位置仅包含 18 个位置。
  • 另外一个三角形的结果是这样的:imgur.com/a/3u7zooo 但看起来他们是站着的,我希望它们是这样的水平形状:imgur.com/a/91D1p7M 它应该由所有成员和水平不垂直。
  • 我不知道这些循环,但如果你将其更改为 Vector3 position = new Vector3(x,0f,y);,它将按所需的方向排列它们。
  • @DubiDuboni 我不明白。你是什​​么意思你只想要大纲?你的意思是,它适用于水平方向?
  • 您的问题不仅仅要求提供大纲。您的原始代码不会尝试仅生成大纲。编辑您的问题以提出要求将使答案无效(并导致您的问题回滚)。至于垂直放置而不是水平放置的单位,这是由于 Vector3 与 Vector2 的关系,并且可以通过使用 (x,n,y) 而不是 (x,y) 轻松更改(其中 n 是一些值,硬编码或其他方式)。
猜你喜欢
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
相关资源
最近更新 更多