改变抛物线的方向以跟随鼠标拖动

Change parabola's direction to follow mouse drag

我正在尝试计算如果一个物体沿着水面被拖动,留在水中的抛物线轨迹。 我认为将轨迹方法与焦点、顶点和准线一起使用是可行的方法。这适用于垂直和水平运动(取决于准线轴)但是随着准线不断移动其轴方向我被卡住了。

这就是我现在的(为垂直移动而写)

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

[RequireComponent(typeof(LineRenderer))]
public class Parabola : MonoBehaviour {

public GameObject pointD, pointF, pointM;
public LineRenderer line;

public Vector3 mouse=Vector3.one, prev;
public Vector3 directrix;
public Vector3 focusPoint, directrixPointMid, directrixPointL, directrixPointR;
public float directrixLength;
public int resolution;
public Vector3 focalLine;
public float focalLenght;
public Vector3 p;
public List<Vector3> points = new List<Vector3>();

void Start () 
{
    prev = mouse;
    line = GetComponent<LineRenderer>();
    line.positionCount = resolution;
}

void Update () 
{
    if(Input.GetMouseButton(0))
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if(Physics.Raycast(ray, out hit, Mathf.Infinity, 1<<LayerMask.NameToLayer("Plane")))
        {
            mouse = new Vector3(hit.point.x,0,hit.point.z);
            if(prev != mouse)
            {
                focalLine = prev - mouse;
                focusPoint = mouse + focalLine.normalized * focalLenght;
                directrixPointMid = mouse +(-focalLine.normalized  * focalLenght);
                directrix = Vector3.Cross(directrixPointMid-focusPoint, Vector3.up);
                directrixPointL = directrixPointMid +(directrix.normalized * (directrixLength/2));
                directrixPointR = directrixPointMid +(-directrix.normalized * (directrixLength/2));

                Debug.DrawRay(mouse, focalLine.normalized*10,Color.green);
                Debug.DrawRay(directrixPointR, directrix.normalized*directrixLength,Color.red);

                pointD.transform.position = directrixPointMid;
                pointF.transform.position = focusPoint;
                pointM.transform.position = mouse;
                prev = mouse;
            }
        }
        points = new List<Vector3>();
        for(float i = -directrixLength/2; i<=directrixLength/2; i+=directrixLength/resolution)
        {
            //float angle = Vector3.Angle(Vector3.forward,focalLine);

            float z = 1/(2*(focusPoint.z-directrixPointMid.z))*Mathf.Pow((Mathf.Abs(directrixPointMid.x)+i)-focusPoint.x,2)+0.5f*(focusPoint.z+directrixPointMid.z);
            float x = directrixPointMid.x+i;
            p = new Vector3(x,1,z);

            //p = new Vector3(x*Mathf.Cos(angle)-z*Mathf.Sin(angle),1,x*Mathf.Sin(angle) + z*Mathf.Cos(angle));
            //p.z = 2*p.x + Mathf.Sin(p.x);
            //p = new Vector3(p.x*Mathf.Cos(angle)-p.z*Mathf.Sin(angle),1,p.x*Mathf.Sin(angle) + p.z*Mathf.Cos(angle));

            points.Add(p);
        }
        line.SetPositions(points.ToArray());

    }
}
}

有一些已注释掉的尝试,但没有任何效果。

我将我的设置更改为使用 y = x^2 并将我的所有坐标设为拖动方向的局部坐标。

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

public class Parabola : MonoBehaviour {

public GameObject linePrefab, pointV;

public float offset, amp, speed;
public int freq;
public float directrixLength;
public int resolution;

private Vector3 mouse, prev;
private Vector3 directrix;
private Vector3 focusPoint, directrixPointMid, directrixPointL, directrixPointR;
private Vector3 focalLine;
private Vector3 p;
private List<List<Vector3>> pointsR = new List<List<Vector3>>();
private List<LineRenderer> lines = new List<LineRenderer>();
public Renderer render;

void Start () 
{
    render.material.SetInt("_Length", resolution);
    render.material.SetVectorArray("_Points", new Vector4[resolution]); 

    prev = mouse;
    int i = 0;
    while(i <= freq)
    {
        GameObject g = Instantiate(linePrefab);
        g.transform.SetParent(transform);
        g.transform.localPosition = Vector3.zero;
        LineRenderer line = g.GetComponent<LineRenderer>();
        line.positionCount = resolution;
        lines.Add(line);
        List<Vector3> lR = new List<Vector3>();
        pointsR.Add(lR);
        i++;
    }
}

void FixedUpdate () 
{
    if(Input.GetMouseButton(0))
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if(Physics.Raycast(ray, out hit, Mathf.Infinity, 1<<LayerMask.NameToLayer("Plane")))
        {
            mouse = new Vector3(hit.point.x,0,hit.point.z);
            StopCoroutine(CalculateParabola(mouse));
            StartCoroutine(CalculateParabola(mouse));
            transform.position = mouse;
            transform.forward = -focalLine;
        }
    }
}
IEnumerator CalculateParabola(Vector3 v)
{
    while(prev != v)
    {
        focalLine = prev - v;
        //calculate a parabola for each n in frequency, make it go wider the higher n is
        for(int n=0; h<=freq; n++)
        {
            pointsR[n] = new List<Vector3>();
            float s = Vector3.Distance(prev.normalized,v.normalized)*speed;
            for(float i = -directrixLength/2; i<=(directrixLength+1)/2; i+=directrixLength/resolution)
            {
                p.x = pointV.transform.localPosition.x+(i*(freq-n+Time.fixedDeltaTime*s));
                p.z = ((amp*(freq-n))*(Time.fixedDeltaTime*s))*-Mathf.Pow(p.x,2)+(1+offset*n);
                pointsR[n].Add(p);
            }
            lines[h].SetPositions(pointsR[n].ToArray());
            //attempt to translate the points to a shader, only for the first parabola for now
            Vector4[] renderPoints = new Vector4[resolution];
            for(int i=0; i<resolution; i++)
            {
                renderPoints[i] = transform.TransformPoint(pointsR[0][i]) - render.transform.position;
            }
            render.material.SetVectorArray("_Points", renderPoints); 
        }
        yield return new WaitForSeconds(0.1f);
        prev = v;
    }
}
}