将精灵弯曲并拉伸到鼠标 click/touch

Curve and stretch a sprite to mouse click/touch

我希望创建一个游戏对象,您可以在其中通过触摸碰撞线上的某处开始拖动它,并通过拉伸精灵并根据拖动点.

为通关添加插图:

开始尝试 Sprite Shape Renderer 创建这些弯曲的精灵图块,但我需要能够使用鼠标光标创建动态图块并调整所有碰撞。

我尝试将 AnchorDragger 脚本添加到 Sprite Shape Renderer 对象:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;

public class AnchorDragger : MonoBehaviour
{
    const int INVALLID_INSERTED_POINT_INDEX = -1;

    public SpriteShapeController spriteShapeController;
    private Spline spline;
    private int inseretedPointIndex = INVALLID_INSERTED_POINT_INDEX;

    void Start()
    {
        spline = spriteShapeController.spline;
        int pointCount = spline.GetPointCount();
        for (var i = 0; i < pointCount; i++)
        {
            Vector3 currentPointPos = spline.GetPosition(i);
            Debug.Log("Point " + i + " position: " + currentPointPos);
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (inseretedPointIndex != INVALLID_INSERTED_POINT_INDEX)
        {
            spline = spriteShapeController.spline;
            spline.SetPosition(inseretedPointIndex, Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1.0f)));
            spriteShapeController.BakeCollider();
        }
    }

    void OnMouseDown()
    {
        Debug.Log("Mouse Down Position:" + Input.mousePosition);
        Vector3 mouseDownPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1.0f));
        Debug.Log("World Position: " + mouseDownPos);
        spline = spriteShapeController.spline;
        int pointCount = spline.GetPointCount();
        int closestPointIndex = int.MaxValue;
        float minDistance = int.MaxValue;
        for (var i = 0; i < pointCount; i++)
        {
            Vector3 currentPointPos = spline.GetPosition(i);
            float distance = Vector3.Distance(currentPointPos, mouseDownPos);
            if (distance < minDistance)
            {
                minDistance = distance;
                closestPointIndex = i;
            }
        }
        spline.InsertPointAt(closestPointIndex, mouseDownPos);
        spline.SetTangentMode(closestPointIndex, ShapeTangentMode.Continuous);
        inseretedPointIndex = closestPointIndex;
        Debug.Log("Inserted point index: " + inseretedPointIndex);
    }

    void OnMouseUp()
    {
        Debug.Log("Mouse Up");
        spline = spriteShapeController.spline;
        spline.RemovePointAt(inseretedPointIndex);
        inseretedPointIndex = INVALLID_INSERTED_POINT_INDEX;
    }
}

基本上是想找出样条曲线上我单击的最近点,然后插入一个新点并将其在 Update 上的位置设置为鼠标所在的位置,然后删除鼠标向上的点。
现在我遇到了一个问题,由于某种原因拖动位置不正确。
我点击的地方,新点位置设置的地方:

即使我尝试玩我点击的地方以及拖动时将鼠标带到的地方,也不知道为什么,可以寻求帮助!

Camera.ScreenToWorldPoint 在这里不合适,因为您不知道要检查距离相机多远,而这对于 z 位置是必需的。不正确的 z 组件会将样条曲线上最近的点提供给与鼠标对齐但不在精灵上的某个点,并且会在意外位置修改样条曲线:

取而代之的是,从相机中绘制一条光线,看看它与精灵所在的平面相交的位置,然后使用该世界位置。

Update中:

void Update()
{
    if (inseretedPointIndex != INVALLID_INSERTED_POINT_INDEX)
    {
        spline = spriteShapeController.spline;

        Ray r = Camera.main.ScreenPointToRay(Input.mousePosition); 
        Plane p = new Plane(Vector3.forward,spriteShapeController.spline.GetPosition(0)); 

        float d; 
        p.Raycast(r,out d); 
        spline.SetPosition(inseretedPointIndex, r.GetPoint(d));

        spriteShapeController.BakeCollider();
    }
}

OnMouseDown中:

void OnMouseDown()
{
    Debug.Log("Mouse Down Position:" + Input.mousePosition);

    Ray r = Camera.main.ScreenPointToRay(Input.mousePosition); 
    Plane p = new Plane(Vector3.forward, spriteShapeController.spline.GetPosition(0)); 

    float d; 
    p.Raycast(r,out d); 

    Vector3 mouseDownPos = r.GetPoint(d);
    Debug.Log("World Position: " + mouseDownPos);