美文网首页
Unity 传送曲线

Unity 传送曲线

作者: 烂醉花间dlitf | 来源:发表于2021-05-07 19:58 被阅读0次

贝塞尔曲线

关于贝塞尔曲线的介绍可以去看看其他更偏理论的博客,这里默认知道这是啥。一般需要三个点就够了:起点,终点,控制点。下面三种方法主要是针对终点的计算有所不同。(前两种之前写的...懒得找了,第三种应该是最复杂的,能理解的话前面的问题就不大)

贝塞尔曲线之直线变曲线

直接使用 transform.position 作为起点,发射 transform.forword 方向上的射线,判断目标是否可传送,可以的话,把控制点吊高(比如计算起点,终点的中间点,再把 y 增加),这样看起来就是一个传送曲线。
缺点:just 看起来,在 VR 项目中,手柄稍微抬高一点点,与地面没有交点的话,就不能传送了。
优点:非常省事

贝塞尔曲线之固定目的地

如果可传送点就几个地方的话,可以考虑这种方式,效果如下:


传送

通过控制朝向,在两个传送点之间切换。思路是先把所有的传送点位置存下来,然后在选择传送点的时候,计算当前朝向与所有传送点的点积(也就是夹角),选点积最大的(也就是夹角最小的)。


丑丑的图示
缺点:需要固定目的地
优点:可以固定目的地

贝塞尔曲线之计算目的地

原理就是设置一个最大的传送范围,然后物体抬得最高的时候,也就是图中 180° 的时候,算出一个当前朝向的最远的一个地方,再用从天而降的射线判断目的地是否可以传送,这样便计算出了贝塞尔曲线的目标点,控制点简单点就像这样,跟起点相切,长度为起点和终点一半的距离。
缺点:要定好最大传送的尺度,也就是说,如果你的地图只有半径 10 米,却设置了 100 的最大距离,那么只有 1/10 的范围是可用的。
优点:相对于固定目的地传送,这种可以在范围内随意传送,自由度高。


丑丑的图示
效果图
有高度
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class NewBehaviourScript : MonoBehaviour
{
    public float MaxTranlateDistance;
    public float MaxTranlateHight;

    private LineRenderer _lineRenderer;

    private void Start()
    {
        _lineRenderer = GetComponent<LineRenderer>();
        _lineRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
        _lineRenderer.startWidth = 0.04f;
        _lineRenderer.endWidth = 0.04f;
        _lineRenderer.numCapVertices = 5;
        _lineRenderer.numCornerVertices = 5;
        _lineRenderer.positionCount = 30;
    }

    private void Update()
    {
        DrawLine();
    }

    private void DrawLine()
    {
        Vector3 startPoint = transform.position;
        Vector3 horizontalForward = Vector3.Cross(transform.right, Vector3.up);
        if (Vector3.Dot(horizontalForward, transform.forward) < 0)
        {
            horizontalForward = -horizontalForward;
        }
        Debug.DrawLine(transform.position, transform.position + Vector3.up, color: Color.green);
        Debug.DrawLine(transform.position, transform.position + transform.right, color: Color.red);
        Debug.DrawLine(transform.position, transform.position + horizontalForward, color: Color.blue);
        float horizontal_t = Vector3.Dot(transform.forward, horizontalForward);
        float t = horizontal_t / 2;
        if (transform.forward.y > 0) // 当抬得比较高的时候,要把 t 的范围从 0.5-0 映射到 0.5-1
        {
            t = -t + 1;
        }
        Vector3 endPoint = transform.position + horizontalForward * t * MaxTranlateDistance;

        // 注意这里我写了碰撞遮罩的检测,所以在场景中要设置好层级
        if (Physics.Raycast(new Ray(endPoint + Vector3.up * MaxTranlateHight, Vector3.down),
            out RaycastHit hit, 100, 1 << LayerMask.NameToLayer(ConstName.layer_translate_target), QueryTriggerInteraction.Collide))
        {
            endPoint = hit.point;
        }
        else
        {
            _lineRenderer.enabled = false;
            return;
        }
        float d = (endPoint - startPoint).magnitude / 2;
        Vector3 controlPoint = transform.position + transform.forward * d;
        Vector3[] bcList = GetBeizerPathPointList(startPoint, controlPoint, endPoint, 30);
        _lineRenderer.positionCount = bcList.Length + 1;
        _lineRenderer.SetPosition(0, startPoint);
        for (int i = 0; i < bcList.Length; i++)
        {
            Vector3 v = bcList[i];
            _lineRenderer.SetPosition(i + 1, v);
        }
        _lineRenderer.enabled = true;
    }

    public static Vector3[] GetBeizerPathPointList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint, int pointNum)
    {
        Vector3[] BeizerPathPointList = new Vector3[pointNum];
        for (int i = 1; i <= pointNum; i++)
        {
            float t = i / (float)pointNum;
            Vector3 point = GetBeizerPathPoint(t, startPoint,
                controlPoint, endPoint);
            BeizerPathPointList[i - 1] = point;
        }
        return BeizerPathPointList;
    }

    private static Vector3 GetBeizerPathPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        return (1 - t) * (1 - t) * p0 + 2 * t * (1 - t) * p1 + t * t * p2;
    }


}

抛物线

手撸一个抛物线,之前写的抛物线找不到了...
缺点:落点不好判断
优点:比较真实

球形差值

TODO

相关文章

网友评论

      本文标题:Unity 传送曲线

      本文链接:https://www.haomeiwen.com/subject/jytnlltx.html