如何计算和创建三角形的位置?

时间:2018-11-05 21:34:21

标签: c# unity3d

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

循环是错误的。它将squadMembers放置在一条线中,另一条线上方。 甚至不接近三角形。 我希望squadMembers呈三角形。

这是运动的部分:但是问题出在计算三角形位置的循环上。我做过的其他编队都很好。

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

2 个答案:

答案 0 :(得分:6)

让我们看看职位列表包含一个简单值n = 3

首先,将x从0循环到2(3 - 1) 然后,对于每个x,从x循环到4-x(3*2 - x - 1 - 1
记住a<ba<=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);
        }
    }

答案 1 :(得分:5)

由于不能保证三角形的单位数完美,因此您应该高估三角形的大小,计算已放置的单位数,然后在达到极限时放弃放置。

首先,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);

    }
}