Unity中利用LineRenderer绘制寻路路径

这篇具有很好参考价值的文章主要介绍了Unity中利用LineRenderer绘制寻路路径。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于A*的寻路路径点生成,这里只做之后的显示以及曲线平滑

这里主要是Catmull-Rom的应用,最终选用的是Centripetal Catmull–Rom spline
unity 显示路径,Unity,unity,游戏引擎

起初想要通过贝塞尔曲线去平滑路径,但是很快便发现路径平滑后它不穿过中途点。
unity 显示路径,Unity,unity,游戏引擎unity 显示路径,Unity,unity,游戏引擎unity 显示路径,Unity,unity,游戏引擎unity 显示路径,Unity,unity,游戏引擎

贝塞尔曲线

unity 显示路径,Unity,unity,游戏引擎

Catmoll-Rom

参考

unity 显示路径,Unity,unity,游戏引擎
由最少4个点进行差值计算,差值结果在p1-p2之间

曲柄是由P’(0) = τ(Pi - Pi-2), P’(1) = τ(Pi + 1 - Pi - 1)
unity 显示路径,Unity,unity,游戏引擎
unity 显示路径,Unity,unity,游戏引擎
unity 显示路径,Unity,unity,游戏引擎
Chordal与Uniform样条曲线的最大区别是对每一个τ都进行了计算实际间隔长度
unity 显示路径,Unity,unity,游戏引擎
Centripetal 则是对这个τ部分又进行了一个幂次方,当幂是0则为Uniform,为1则是Chordal,而0.25-0.5则是Centripetal

unity 显示路径,Unity,unity,游戏引擎
这张图解释了不选用默认样条的原因文章来源地址https://www.toymoban.com/news/detail-610125.html

//获取lilneRenderer组件并初始化
void GetLineRenderer()
    {
        
        if (_lr == null){Debug.Log($"{this.transform.name}: line renderer 获取失败");return;}

        if (lineMat == null){Debug.Log("line renderer材质不能为空");return;}

        //line renderer 设置;
        _lr.materials = lineMat;
        _lr.useWorldSpace = true;
        
        //颜色渐变,linerenderer会赋值给顶点色
        _lr.colorGradient = gradient;
        _lr.shadowCastingMode = ShadowCastingMode.Off;
        _lr.lightProbeUsage = LightProbeUsage.Off;
        _lr.reflectionProbeUsage = ReflectionProbeUsage.Off;
        _lr.textureMode = LineTextureMode.RepeatPerSegment;
        _lr.alignment = LineAlignment.TransformZ;
        _lr.widthCurve = width;
        _lr.useWorldSpace = true;

    }

 //这步可省略,可以在inspector里手动设置
 private Gradient GetColorGradient()
    {
        var g = new Gradient();   
        // Populate the color keys at the relative time 0 and 1 (0 and 100%)
        var colorKey = new GradientColorKey[4];
        colorKey[0].color = Color.black;
        colorKey[0].time = 0.1f;
        colorKey[1].color = Color.white;
        colorKey[1].time = 0.2f;    
        colorKey[2].color = Color.white;
        colorKey[2].time = 0.8f;  
        colorKey[3].color = Color.black;
        colorKey[3].time = 0.9f;
        var alphaKey = new GradientAlphaKey[1];
        alphaKey[0].alpha = 1.0f;
        alphaKey[0].time = 0.0f;

        g.SetKeys(colorKey, alphaKey);
        return g;
    }
    
private void SetPath()
    {
        transform.localRotation = Quaternion.Euler(new Vector3(0,0,0));

		//高度控制
        for (int i = 0; i < _pathArray.Count; i++)
        {
            _pathArray[i] += Vector3.up * height;
        }
        
        _lr.enabled = true;
        //将传入的寻路点输入,生成平滑点,smooth越高,差值出的平滑点越多
        _pathArray = GetCurve(_pathArray, smooth);
  
        _lr.positionCount = _pathArray.Count;
        for (int i = 0; i < _pathArray.Count; i++)
        {
            _lr.SetPosition(i, _pathArray[i]);
        }
        
        //需要将立面旋转为平面
        transform.localRotation = Quaternion.Euler(new Vector3(90,0,0));
        
    }
    
 	//根据输入点重新分布并平滑曲线点
    List<Vector3> GetCurve( List<Vector3> pathArray, int smooth = 4)
    {
        if (pathArray.Count < 3)
        {
            return pathArray;
        }
        List<Vector3> pathss = new List<Vector3>();
        CatmullRomCurve curve;
        Vector3 pt, p0, p1, p2, p3;

        for (int i = 0; i <= pathArray.Count - 2; i++)
        {
            p1 = pathArray[i];
 
            p0 = i == 0 ? p1 : pathArray[i - 1];
            p2 = pathArray[i + 1];
            p3 = i == pathArray.Count - 2 ? p2 : pathArray[i + 2];
            curve = new CatmullRomCurve(p0, p1, p2, p3, 0.5f);
            int detail = smooth;
            
            for( int j = 1; j < detail; j++ ) {
                float t = j / ( detail - 1f );
                pt = curve.GetPoint( t );
                pathss.Add(pt);
            }
        }

        return pathss;
    }

 //https://en.wikipedia.org/wiki/Centripetal_Catmull–Rom_spline
    public struct CatmullRomCurve {

        public Vector3 p0, p1, p2, p3;
        public float alpha;

        public CatmullRomCurve( Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float alpha ) {
            ( this.p0, this.p1, this.p2, this.p3 ) = ( p0, p1, p2, p3 );
            this.alpha = alpha;
        }

        // Evaluates a point at the given t-value from 0 to 1
        public Vector3 GetPoint( float t ) {
            // calculate knots
            const float k0 = 0;
            float k1 = GetKnotInterval( p0, p1 );
            float k2 = GetKnotInterval( p1, p2 ) + k1;
            float k3 = GetKnotInterval( p2, p3 ) + k2;

            // evaluate the point
            float u = Mathf.LerpUnclamped( k1, k2, t );
            Vector3 A1 = Remap( k0, k1, p0, p1, u );
            Vector3 A2 = Remap( k1, k2, p1, p2, u );
            Vector3 A3 = Remap( k2, k3, p2, p3, u );
            Vector3 B1 = Remap( k0, k2, A1, A2, u );
            Vector3 B2 = Remap( k1, k3, A2, A3, u );
            return Remap( k1, k2, B1, B2, u );
        }

        static Vector3 Remap( float a, float b, Vector3 c, Vector3 d, float u ) {
            return Vector3.LerpUnclamped( c, d, ( u - a ) / ( b - a ) );
        }

        float GetKnotInterval( Vector3 a, Vector3 b ) {
            return Mathf.Pow( Vector3.SqrMagnitude( a - b ), 0.5f * alpha );
        }

    }


//移除角色身后的路径点
 void PlayerMovingForward()
    {
        if (playerPos == null || _lr == null || _lr.positionCount == 0 || _pathArray.Count == 0) return;
        
        Vector3 p1 = _lr.GetPosition(0);
        Vector3 p2 = playerPos.position;
        Vector3 dir = Vector3.Normalize(p1 - p2);
        var cross = Vector3.Cross(playerPos.right, dir);
        //>0 p1 在 p2 后面, <0 p1 在 p2 前面,移除身后点
        if (cross.y > 0)
        {
            if (_pathArray.Count == 0)
            {
                //0点后不再进行删除
                return;
            }
            _pathArray.RemoveAt(0);
            _lr.positionCount = _pathArray.Count;
            for (int i = 0; i < _pathArray.Count; i++)
            {
                _lr.SetPosition(i, _pathArray[i]);
            }
        }
    }
    

到了这里,关于Unity中利用LineRenderer绘制寻路路径的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity LineRenderer的简单使用

    一、创建LineRenderer 1、直接创建 2、添加LineRenderer组件给GameObject 二、组件属性 常用代码

    2024年02月11日
    浏览(36)
  • 【Unity】LineRenderer画线拐点的网格变形问题

    正常情况下,使用Unity中画线工具LineRenderer。可以画出期望的直线。 但当拐点处,两点的距离过小,并且线的宽度不是特别细的情况下。组件动态生成的线会发生变形。 这是因为LineRenderer是根据填入的点位Positions和宽度Width来生成网格。如果两点间距过近,并且有一定的宽度

    2024年02月16日
    浏览(40)
  • 【Unity开发】给LineRenderer添加碰撞体(使用MeshCollider)

    在这里选择使用MeshCollider组件给Line添加碰撞体。 首先创建Line的Mesh 通过查阅Unity官方文档我们可以得知,使用BakeMesh函数可以获取到Line的Mesh。 创建MeshCollider组件并添加Mesh信息

    2024年02月15日
    浏览(45)
  • 【Unity3D】线段渲染器LineRenderer

    1 LineRenderer 简介         LineRenderer 组件用于绘制线段,可以调整线段条数、端点坐标、颜色、宽度等属性,其属性面板如下: Materials :线段材质,最好设置为 Default-Line; Positions-Size :线段端点个数; Positions-Element :线段端点值; Width :线段宽度,可以是不等宽的;

    2023年04月08日
    浏览(52)
  • unity 曲线可视化图表制作(lineRenderer + 贝塞尔曲线)

    需求要实现一个动态变化的曲线 思路: 分为两部分:画线和平滑曲线 首先解决画线问题: 1.lineRenderer 2.texture的setpixel 肯定选已经做好的轮子1啦 平滑曲线思路: 1.抛物线 2.贝塞尔曲线 抛物线做连续的曲线太抽象了 肯定选贝塞尔曲线 先了解一下贝塞尔曲线 一次贝塞尔 对应

    2023年04月08日
    浏览(46)
  • Unity 中的简单A*寻路 (AStar寻路)实现

    本文实现的A*算法,未经过大量的优化,后续文章会进一步实现优化 后篇:A*优化讨论 结点类: 结点管理类: 单例模板: 测试脚本: 新建一个场景,将测试脚本挂载在任意物体上 新建一个画布,并添加一个按钮。其它ui元素可随意设定 将按钮关联Init方法 后续优化文章:

    2024年02月03日
    浏览(53)
  • 【Unity】Unity寻路系统讲解及Navigation实际应用

    Unity常用的寻路方式主要有以下几种: 路点寻路(WayPoint) 单元格寻路(Grid) 导航系统(Navigation) 路点寻路就是在地图上指定一些路点,让角色在路点之间移动。常用于一些固定路线的敌人或物体。 优点:路点寻路的优点是实现起来比较简单,且占用资源少、计算开销低

    2024年02月01日
    浏览(94)
  • Unity 2022 版本 寻路 NavMesh

    官方教程地址 https://docs.unity3d.com/Packages/com.unity.ai.navigation@1.1/manual/index.html 首先装包 先给地图 和 阻挡 设置为静态 然后给地上行走的地方 添加组件 可以直接bake 然后会显示蓝色的可行走路径 player 添加插件 然后给角色添加脚本 搞定 场景内添加两个圆柱体 并设置为静态 起始

    2024年02月07日
    浏览(41)
  • Unity寻路A星算法

    在Unity中实现A星(A*,A-Star)算法是一种用于寻找两点之间最短路径的广泛应用的技术。该算法结合了启发式搜索与图论中的Dijkstra算法,通过评估每个节点到起点和终点的成本来确定最优路径。 以下是Unity中使用A*寻路算法的一个简要步骤和实例: 实现步骤概览: 构建网格

    2024年01月17日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包