Кривая и растянуть спрайт до щелчка мыши / касания - PullRequest
1 голос
/ 17 октября 2019

Я хочу создать игровой объект, где вы можете начать его перетаскивать, коснувшись где-нибудь на линии его столкновения, и создать эти «динамические фигуры», растягивая спрайты и перенастраивая внешний вид и столкновение спрайтов в соответствии с точкой перетаскивания.

Добавление иллюстрации для оформления: enter image description here

Начал играть с 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 туда, где находится мышь, и удалите точку на мышь вверх. Прямо сейчас у меня проблема, когда позиция перетаскивания по какой-то причине неверна. Где я щелкнул, где установлена ​​новая точка: enter image description here

, даже когда я пытался играть с тем, где я щелкаю и куда я приношу свою мышь при перетаскивании, не знаю почему, можете воспользоваться помощью!

1 Ответ

1 голос
/ 18 октября 2019

Camera.ScreenToWorldPoint здесь не подходит, потому что вы еще не знаете, как далеко от камеры можно проверить, что необходимо для положения z. Неправильный компонент z дал бы ближайшую точку на сплайне в некоторой точке, с которой мышь выровнена, но не на спрайте, и изменил бы сплайн в неожиданной позиции:

enter image description here

Вместо этого нарисуйте луч из камеры и посмотрите, где он пересекается с плоскостью, на которой живет спрайт, и используйте эту позицию в мире.

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

In 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);
...