【问题标题】:How to create positions with an equal distance on a circle?如何在圆上创建等距的位置?
【发布时间】:2021-11-19 23:37:55
【问题描述】:

我正在编写一个代表圆形网格的脚本。随着层与中心的距离增加,每层中的对象数量按比例增加,因此每个 tile 之间的距离应该保持不变。我试图通过舍入鼠标世界位置来计算每个 tile 的近似值,但这固有地导致了一些问题,例如围绕起始角度抽搐并在鼠标到达之前移动对象。 这是一个完全糟糕的方法还是我错过了什么? 代码如下:

customGrid.cs

using UnityEngine;

public class customGrid : MonoBehaviour
{
    [SerializeField] private Camera mainCamera;
    [SerializeField] private LayerMask layerMask; // this is a simple LayerMask attached to a simple Plane object

    public GameObject structure;

    Vector3 truePos;
    public int maxLayers = 1;
    public int minLayers = 0;
    public float objectSize = 1.5f;

    public float radius = 0f;
    void LateUpdate()
    {
        Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit raycastHit, float.MaxValue, layerMask))
        {
            float angleRadian = Mathf.Atan2(raycastHit.point.x, raycastHit.point.z);
            float cursorDistanceFromOrigin = Vector3.Distance(Vector3.zero, new Vector3(raycastHit.point.x, 0, raycastHit.point.z));
            var circumference = 2 * Mathf.PI * radius;
            var quantization = 360 / (circumference / objectSize);

            float objectDistanceFromOrigin = Mathf.Floor(cursorDistanceFromOrigin / objectSize) * objectSize;

            var maxDistance = objectSize * maxLayers;
            var minDistance = objectSize * minLayers;

            objectDistanceFromOrigin = Mathf.Clamp(objectDistanceFromOrigin, minDistance, maxDistance);

            radius = objectDistanceFromOrigin;
            if (radius < 1) return;

            var degree = angleRadian * Mathf.Rad2Deg;
            degree = Mathf.Round(degree / quantization) * quantization;
            angleRadian = degree * Mathf.Deg2Rad;
            truePos.x = Mathf.Sin(angleRadian) * radius;
            truePos.y = 0;
            truePos.z = Mathf.Cos(angleRadian) * radius;

            RepositionObject();
        }
    }

    private void RepositionObject()
    {
        structure.transform.position = truePos;
        var dir = truePos - Vector3.zero;
        dir = Vector3.Normalize(dir);
        structure.transform.rotation = Quaternion.LookRotation(dir);
    }
}

我期待的是这样的网格:

【问题讨论】:

  • 你能大致画出你希望网格线的样子吗?
  • @AndrewWilliamson 当然!我在问题中添加了一张图片。

标签: c# algorithm unity3d trigonometry


【解决方案1】:

如果您希望瓷砖之间的距离保持不变,那么您需要从一组已知的瓷砖中进行选择。

最简单的使用方法是十六进制平铺。除非您有充分的理由不这样做,否则我建议您这样做。

https://en.wikipedia.org/wiki/Tessellation 包括其他,例如https://en.wikipedia.org/wiki/Voderberg_tiling,它以您想要的方式螺旋(以非常非矩形为代价)。

如果您愿意放宽距离规则,您可以轻松创建许多形状变化的平铺。如果将宽度设置为高度的 1.0471975512 倍,并将“瓷砖”制成圆形部分,您将非常接近近似正方形,每层比前一层多 6 个。你可以决定你想要什么。

请注意,除了像六角平铺这样的常规平铺外,任何类型的物理操作都会变得困难。随着游戏的发展,这将成为您的问题。

【讨论】:

    猜你喜欢
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2015-06-09
    相关资源
    最近更新 更多