如何在圆上创建等距离的位置?

问题描述 投票:0回答:1

我正在编写一个应该代表圆形网格的脚本。随着层与中心的距离增加,每层中的对象数量成比例增加,因此每个tile之间的距离应保持恒定。我尝试通过舍入鼠标世界位置来动态计算每个tile的近似值,但这本质上会导致一些问题,例如围绕起始角度抽搐以及在鼠标到达那里之前移动对象。

这是一个完全糟糕的方法还是我错过了什么?

这是代码:

自定义Grid.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);
    }
}

我期待这样的网格:

c# algorithm unity-game-engine trigonometry
1个回答
1
投票

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

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

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

如果您愿意放宽距离规则,您可以轻松创建大量形状不同的平铺。如果将宽度设置为高度的 1.0471975512 倍,并将“图块”设置为圆形部分,则您将非常接近近似正方形,每层比上一层多 6 个。你可以决定你想要的方式。

请注意,除了六角形平铺等常规平铺之外的任何内容都会使执行任何类型的物理操作变得困难。随着你的游戏的发展,这将成为你的一个问题。

© www.soinside.com 2019 - 2024. All rights reserved.