Unity2D Sprite虚线描边,非Shader

近期要做一个虚线描边的效果(当然实线也是一样实现的,只需要把图片换成实线即可),但不会写Shader,网上找的效果也不是很合适,于是就找别方法来实现这一操作。项目主要用到PolygonCollider2D,分两种方法实现,一种是用LineRenderer,另一种是通过使用Ferr2DTerrainTool地形插件(Ferr2D插件的话,需要大家自己去寻找一下),那么下面开始介绍实现的方法:

1、LineRenderer的实现方法

(1)需要准备的设置

首先我们需要准备一条续虚线段,如这种的

对图片的设置如下(用于做材质):

 接下来创建一个材质球,将其放入Resources文件夹中,材质球设置如下:

这个材质球用过改版Tiling的值,在LineRenderer中来实现虚线的效果(有兴趣的话可以新创建一个LineRenderer,观察一下)。

(2)代码实现

 现在要描边的游戏物体身上挂载PolygonCollider2D组件(如果感觉系统自动给的PolygonCollider2D的点不准确的话,可以搜一些能让点准确的脚本辅助一下)。

实现原理:让LineRenderer来获取PolygonCollider2D所有的点,来进行画线操作。当PolygonCollider2D的Path有多个时,要创建出相同数量的物体并搭载上LineRenderer组件。

代码如下:

public class OutLineLiner : MonoBehaviour
{
    PolygonCollider2D polygon;
    List<LineRenderer> lines = new List<LineRenderer>();
    private Material material;
    private Vector2 tiling;
    private int mainTexProperty;
    // 线长
    private float lineLen;
    // 密度
    private float density = 1.5f;
    Vector2[] polygonPos;

    void Start()
    {
        polygon = GetComponent<PolygonCollider2D>();
        //记录材质上Shader的ID
        mainTexProperty = Shader.PropertyToID("_MainTex");
        for (int i = 0; i < polygon.pathCount; i++)
        {
            //通过Path的数量创建相应数量的新物体,并挂载LineRenderer组件
            GameObject go = new GameObject();
            go.transform.SetParent(transform);
            lines.Add(go.AddComponent<LineRenderer>());
            //当前物体上的LineRenderer的相关设置
            lines[i].material = Resources.Load<Material>("XuXian1");
            lines[i].widthMultiplier = 0.1f;
            lines[i].loop = true;
            lines[i].useWorldSpace = false;
            lines[i].numCornerVertices = 10;
            lines[i].numCapVertices = 1;
            if (transform.name.Equals("OutLine"))
            {
                lines[i].sortingLayerName = "WayPoint";
                lines[i].sortingOrder = GetComponentInParent<SpriteRenderer>().sortingOrder;
            }
            else
            {
                lines[i].sortingLayerName = "WayPoint";
                lines[i].sortingOrder = GetComponent<SpriteRenderer>().sortingOrder;
            }
            material = lines[i].material;
            //通过获取当前PolygonCollider2D的Path中点的数量,赋值给LineRenderer的点的数量
            lines[i].positionCount = polygon.GetPath(i).Length;
            //获取当前PolygonCollider2D的Path中点的详细信息
            polygonPos = polygon.GetPath(i);
            //画线
            for (int j = 0; j < lines[i].positionCount; j++)
            {
                lines[i].SetPosition(j, transform.TransformPoint(polygonPos[j]));
                lineLen = LineLength(lines[i]);
                // 根据线段长度计算Tiling
                tiling = new Vector2(lineLen * density, 0);
                // 设置Tiling
                material.SetTextureScale(mainTexProperty, tiling);
            }
        }
    }

    //获取线段的长度
    private float LineLength(LineRenderer line)
    {
        float Liner = 0;
        for (int i = 1; i < line.positionCount; ++i)
        {
            Liner += (line.GetPosition(i) - line.GetPosition(i - 1)).magnitude;
        }
        return Liner;
    }
}

效果如下:

单Path

 多Path

1、Ferr2D的实现方法

 (1)需要准备的设置

虚线图片和材质球的设置和上面LineRenderer的一样,下面我们先创建一个TerrainMaterial:

 

 将之前创建的材质球拖入到TerrainMaterial中

 让我们创建一个Ferr2D地形

 

 对Ferr进行设置,让其只显示边缘:

 

 之后放入Resources文件夹中。

开始上代码:

public class OutLineFerr : MonoBehaviour
{
    PolygonCollider2D polygon;
    Ferr2DT_PathTerrain terrain;
    List<Vector2> terrainPos = new List<Vector2>();

    void Start()
    {
        polygon = GetComponent<PolygonCollider2D>();
        //通过Path的数量复制相应数量的Ferr
        for (int i = 0; i < polygon.pathCount; i++)
        {
            GameObject go = Instantiate(Resources.Load("edge")) as GameObject;
            go.transform.SetParent(transform);
            go.transform.localPosition = Vector3.zero;
            terrain = go.GetComponent<Ferr2DT_PathTerrain>();
            CreatTerrain(polygon.GetPath(i));
        }
    }

    //创建Ferr
    public void CreatTerrain(Vector2[] pos)
    {
        terrainPos.Clear();
        //记录PolygonCollider2D的点的详细信息
        terrainPos.AddRange(pos);
        terrain.ClearPoints();
        //给Ferr添加所有点的信息
        for (int i = 0; i < terrainPos.Count; i++)
        {
            terrain.AddPoint(transform.TransformDirection(terrainPos[i]), i, Ferr.PointType.Sharp);
        }
        terrain.PathData.SetDirty();
        //创建Ferr
        terrain.Build(true);
        terrain.transform.GetComponent<Renderer>().sortingLayerName = "WayPoint";
        terrain.GetComponent<MeshRenderer>().sortingOrder = GetComponentInParent<Renderer>().sortingOrder;
    }
}

 效果如下(这里的图片换了个圆角的虚线段):

 那么这次虚线描边的分享到此结束啦,希望能对大家有帮助♥♥!

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的Unity描边shader的示例代码: ``` Shader "Custom/Outline" { Properties { _MainTex ("Texture", 2D) = "white" {} _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Width", Range (0.002, 0.1)) = 0.01 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Opaque"} LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _OutlineColor; float _OutlineWidth; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // calculate the outline color fixed4 outline = _OutlineColor; float2 texelSize = 1.0 / _ScreenParams.xy; float2 offset[4] = float2[]( float2(texelSize.x, 0), float2(-texelSize.x, 0), float2(0, texelSize.y), float2(0, -texelSize.y) ); for (int j = 0; j < 4; j++) { outline += tex2D(_MainTex, i.uv + _OutlineWidth * offset[j]); } outline /= 5.0; // mix the texture and outline color return lerp(outline, col, col.a); } ENDCG } } FallBack "Diffuse" } ``` 这个shader的核心思想是在每个像素周围采样一些颜色,并将它们平均值作为描边颜色。可以通过调整 `_OutlineWidth` 属性来控制描边的宽度,通过调整 `_OutlineColor` 属性来控制描边的颜色。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值