将屏幕鼠标位置转换为 -1 和 1 之间的本地鼠标位置

Converting screen mouse position to local mouse position between -1 and 1

我在 Unity 中有一个 2D tile 游戏项目,其中每个 tile 的大小为(例如)32 x 32 像素,但在网格中,tile 被映射到完整的整数坐标,例如 tile0x0 y0tile1x1 y0tile2x2 y0tile10x2 y1,等等(如果我没记错的话,这个映射是由于将 sprite sheet 中的 pixel per unit size 设置为例如 32px,对吗?)

无论如何,玩家应该可以用鼠标拖动方块 left/right/up/down,我希望方块随鼠标位置一起拖动。我遇到的问题是我不知道如何将全局鼠标坐标转换为拖动图块的局部 space,特别是转换为 -1 和 1 之间的范围,因为拖动距离已标准化到那个范围。

在我的 Update() 方法中,我有以下代码:

if (_isMouseDown && sourceTile != null)
{
    _isDraggingTile = true;
    Vector3 dragDistance = Input.mousePosition - _originMousePosition;
    dragDistance.Normalize();

    GridCell targetCell;

    /* Check mouse up/down drag. */
    float f = Vector3.Dot(dragDistance, Vector3.up);
    if (f >= 0.5f)
    {
        targetCell = sourceTile.gridCell.upNeighbor;
    }
    else if (f <= -0.5f)
    {
        targetCell = sourceTile.gridCell.downNeighbor;
    }
    else
    {
        /* Check mouse left/right drag. */
        f = Vector3.Dot(dragDistance, Vector3.right);
        targetCell = f >= 0.5f ? sourceTile.gridCell.rightNeighbor : sourceTile.gridCell.leftNeighbor;
    }

    if (Vector3.Distance(_originMousePosition, Input.mousePosition) > _globals.tileDragThreshold)
    {
        if (targetCell != null)
        {
            SetTargetTile(targetCell.tile);
            ResolveMove();
        }
    }
}

代码检查鼠标被拖动到哪个方向,并在某个阈值后将拖动的图块与相邻网格单元格中的图块切换 (targetCell)。我想要实现的是拖动的图块跟随鼠标位置直到交换发生。

谁能告诉我如何将鼠标位置转换成这个位置,以便相应地调整拖动的图块的位置?

您可以在图块上添加一个不可见的平面,以便您可以使用光线投射和命中位置来调整图块。

考虑到您所有的图块位置都存储在一个集合中,您可以在按下鼠标时找到最近的图块。这将成为您当前的磁贴。然后你把它移动到飞机上给定的位置。

当鼠标位置距离当前图块的初始位置太远时,您将再次迭代该集合以找到最近的图块位置并将您的图块对齐到该新位置。您还需要更新上下文,以便磁贴现在分配给该新位置。

伪代码应该是这样的:

Tile currentTile = null;
bool movement = false;
void Update(){

    if(Input.GetMouseButtonDown(0)){
       Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
       RaycastHit hit;
       Physics.Raycast(ray, out hit);
       currentTile = GetClosestTile(hit.position); 
       movement = true;
    }
    else if (Input.GetMouseButton(0))
    {
       if(movement == false){return;}
       Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
       RaycastHit hit;
       Physics.Raycast(ray, out hit);
       if(PositionOutOfBound(hit.position) == true){
            Tile newTile = GetClosestTile(hit.position);
            newTile.currentSprite = currentTile.currentSprite;
            currentTile.currentSprite = null;
            movement = false;
            return;
       }
       currentTile.currentSprite.transform.position = hit.position;
    }
}

这个想法是,当您按下时,演员会找到最近的图块并分配给当前图块。

下一帧,一直按下去,进入第二段,这次看位置是不是离PositionOutOfBound太远了。如果足够远,您可以重用 GetClosestTile。返回的图块接收 sprite(我假设您为图块使用了 sprite),currentTile 移除了 sprite 并将 movement 设置为 false 以避免再次执行操作。

如果您距离初始图块 (currentTile) 不够远,则 PositionOutOfBound returns false 并且您只需让精灵随鼠标位置四处移动。您不想移动图块,而只想移动与其链接的精灵。

同样,这只是扩展 pseudo-code,但您可以轻松找到有关如何找到最近点等的示例。

我不知道规格,但我有一个没有 rigidbody 的拖动对象的通用代码。检查您是否可以根据需要自定义此代码。

void Update ()
    {
        if (Input.GetMouseButton (0)) {

            Vector3 point = Camera.main.ScreenToWorldPoint (Input.mousePosition);

            transform.position = Vector3.MoveTowards (transform.position, new Vector3 (point.x, point.y, transform.position.z), 1);


        }

    }

此代码当前正在移动附加此脚本的 GameObject,因为 transform.position 表示当前 GameObject's transform