如何统一围绕PolygonCollider2D突出显示?

时间:2016-08-25 19:23:08

标签: c# unity3d collider

我的问题是标题。我和团结一起玩回到学校,我决定做一个小风险类型的游戏。

基本上我有我的地图,当我点击我的一个地区(我有一个多边形对撞机周围,附加一个点击方法,目前只是切换一个小盒子精灵测试)我想要突出我选择的领域周围的边缘(多边形对撞机覆盖的女巫的边缘)。所以我想知道是否有可能根据对撞机制作高光效果,或类似的东西。

我目前的计划是将所有地区的边缘Photoshop变成精灵,然后像测试精灵一样切换它们以创造效果,但如果我能用更简单的时间有效地完成它,那就太棒了!

enter image description here

如果可以的话,感谢您的帮助,并询问您是否需要更多信息!

4 个答案:

答案 0 :(得分:1)

虽然这不会勾勒出对撞机(除非它是网格对撞机),但这个着色器将使用所选颜色勾勒出网格:

Shader "Custom/OutlineDiffuseShader"
{
    Properties{
        _Color("Main Color", Color) = (.5,.5,.5,1)
        _OutlineColor("Outline Color", Color) = (0,0,0,1)
        _Outline("Outline width", Range(.002, 0.03)) = .002
        _MainTex("Base (RGB)", 2D) = "white" { }
    }

        CGINCLUDE
#include "UnityCG.cginc"

        struct appdata {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
    };

    struct v2f {
        float4 pos : POSITION;
        float4 color : COLOR;
    };

    uniform float _Outline;
    uniform float4 _OutlineColor;

    v2f vert(appdata v) {
        // just make a copy of incoming vertex data but scaled according to normal direction
        v2f o;
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

        float3 norm = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, v.normal));
        float2 offset = TransformViewToProjection(norm.xy);

        o.pos.xy += offset * o.pos.z * _Outline;
        o.color = _OutlineColor;
        return o;
    }
    ENDCG

        SubShader{
        //Tags {"Queue" = "Geometry+100" }
        CGPROGRAM
#pragma surface surf Lambert

        sampler2D _MainTex;
    fixed4 _Color;

    struct Input {
        float2 uv_MainTex;
    };

    void surf(Input IN, inout SurfaceOutput o) {
        fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb;
        o.Alpha = c.a;
    }
    ENDCG

        // note that a vertex shader is specified here but its using the one above
        Pass{
        Name "OUTLINE"
        Tags{ "LightMode" = "Always" }
        Cull Front
        ZWrite On
        ColorMask RGB
        Blend SrcAlpha OneMinusSrcAlpha
        //Offset 50,50

        CGPROGRAM
#pragma vertex vert
#pragma fragment frag
        half4 frag(v2f i) :COLOR{ return i.color; }
        ENDCG
    }
    }

        SubShader{
        CGPROGRAM
#pragma surface surf Lambert

        sampler2D _MainTex;
    fixed4 _Color;

    struct Input {
        float2 uv_MainTex;
    };

    void surf(Input IN, inout SurfaceOutput o) {
        fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb;
        o.Alpha = c.a;
    }
    ENDCG

        Pass{
        Name "OUTLINE"
        Tags{ "LightMode" = "Always" }
        Cull Front
        ZWrite On
        ColorMask RGB
        Blend SrcAlpha OneMinusSrcAlpha

//      CGPROGRAM
//#pragma vertex vert
//#pragma exclude_renderers gles xbox360 ps3
//      ENDCG
        SetTexture[_MainTex]{ combine primary }
    }
    }

        Fallback "Diffuse"
}

我没有写这个着色器;它是你可以找到的众多变种之一。

您可以通过设置材质的着色器将其应用于游戏对象,如下所示:

gameObject.renderer.material.shader = SelectedShader;

其中SelectedShader是公共字段(不是属性),以便您可以通过检查器将大纲着色器绑定到该变量。请务必保留对前一个着色器的引用,以便在未选中时返回。

您可以通过在材质上设置轮廓来选择轮廓的颜色:

gameObject.renderer.material.SetColor("_OutlineColor", outlineColor);

希望这足够接近!

答案 1 :(得分:1)

enter image description here

几个月前我做了类似的事情。可以使用LineRendererPolygonCollider2D来完成。你必须知道如何以新用户的身份阅读文档,因为它有很多你不了解的信息。

如何执行此操作的步骤:

1 。从代码中创建新的LineRenderer

2 。将材质分配到新的线条渲染器,设置宽度和颜色。

3 。从PolygonCollider2D获取points,返回PolygonCollider2D中点数的数组。

4 。点击这些点并使用TransformPoint函数将每个点从本地空间转换为世界空间..

5 。将LineRenderer的{​​{3}}设置为积分的Length加1.我们需要额外的1才能关闭我们正在画画。

绘制线

6 。最后,循环点并通过使用SetVertexCount函数更改LineRenderer的位置来绘制线条。

LineRenderer.SetPosition(currentLoop, pointsArray[currentLoop]);

由于这是2D,您可能需要修改pointsArray的Z轴以确保Object在每个GameObject前面显示。

7 。通过从最后pointsArray.Length)点位置绘制一条新线到第一个来关闭该线( pointsArray [0])指向。

LineRenderer.SetPosition(pointsArray.Length, pointsArray[0]);

以下是一个可以完全执行此操作的功能。你可以扩展它以支持其他2D碰撞器。只需创建一个脚本并将其中的代码复制一下即可。将附加了PolygonCollider2D的Sprite拖动到myGameObject插槽,然后单击Play。它将在该精灵上绘制线条。

highlightAroundCollider(pColider, Color.yellow, Color.red, 0.1f);功能可让您在调用时提供选项,例如设置sizecolor

using UnityEngine;
using System.Collections;

public class LineDrawerTest : MonoBehaviour
{
    public GameObject myGameObject;
    private PolygonCollider2D pColider;

    protected void Start()
    {
        pColider = myGameObject.GetComponent<PolygonCollider2D>();
        highlightAroundCollider(pColider, Color.yellow, Color.red, 0.1f);
    }


    void highlightAroundCollider(Component cpType, Color beginColor, Color endColor, float hightlightSize = 0.3f)
    {
        //1. Create new Line Renderer
        LineRenderer lineRenderer = gameObject.GetComponent<LineRenderer>();
        if (lineRenderer == null)
        {
            lineRenderer = cpType.gameObject.AddComponent<LineRenderer>();

        }

        //2. Assign Material to the new Line Renderer
        lineRenderer.material = new Material(Shader.Find("Particles/Additive"));

        float zPos = 10f;//Since this is 2D. Make sure it is in the front

        if (cpType is PolygonCollider2D)
        {
            //3. Get the points from the PolygonCollider2D
            Vector2[] pColiderPos = (cpType as PolygonCollider2D).points;

            //Set color and width
            lineRenderer.SetColors(beginColor, endColor);
            lineRenderer.SetWidth(hightlightSize, hightlightSize);

            //4. Convert local to world points
            for (int i = 0; i < pColiderPos.Length; i++)
            {
                pColiderPos[i] = cpType.transform.TransformPoint(pColiderPos[i]);
            }

            //5. Set the SetVertexCount of the LineRenderer to the Length of the points
            lineRenderer.SetVertexCount(pColiderPos.Length + 1);
            for (int i = 0; i < pColiderPos.Length; i++)
            {
                //6. Draw the  line
                Vector3 finalLine = pColiderPos[i];
                finalLine.z = zPos;
                lineRenderer.SetPosition(i, finalLine);

                //7. Check if this is the last loop. Now Close the Line drawn
                if (i == (pColiderPos.Length - 1))
                {
                    finalLine = pColiderPos[0];
                    finalLine.z = zPos;
                    lineRenderer.SetPosition(pColiderPos.Length, finalLine);
                }
            }
        }

         //Not Implemented. You can do this yourself
        else if (cpType is BoxCollider2D)
        {

        }
    }

    void Update()
    {

    }
}

答案 2 :(得分:0)

这是我使用的解决方案。它使用Line Renderer,最终将在Unity 5.5中成为美女。

我得到了用作按钮的对象。它有PoligonCollider2D,一个LineRenderer和这个sript。线分渲染器也必须在分辨率更改后重绘。所以我以特定的分辨率配置我的poligon对撞机,你可以在Game窗口中配置。在我的脚本中,我使用689 * 500,即16/9分辨率。 Canvas是屏幕空间 - 相机,并且具有1.7777778值的宽高比兼容。

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

public class PolygonButton : MonoBehaviour {

    public string param;

    public System.Action onClick;

    float animSpeed = 1.5f;
    IEnumerator anim;
    bool animating;
    Rect res; 
    Camera mainCam;
    float theWidth = 689;

    void Start()
    {
        mainCam = GameObject.FindObjectOfType<Camera>();
        res = mainCam.pixelRect;
        anim = buttonAnimation();
        animating = false;
        GetComponent<LineRenderer>().material.SetColor("_Color", new Color32(255, 255, 0, 0));

        LineRenderer lr = GetComponent<LineRenderer>();
        PolygonCollider2D polColliedr = GetComponent<PolygonCollider2D>();
        int i = 0;
        lr.numPositions = polColliedr.points.Length + 1;
        foreach (Vector2 point in polColliedr.points)
        {
            lr.SetPosition(i, point);
            i++;
        }
        lr.SetPosition(i, lr.GetPosition(0));

        //change scale for different aspect ratio

        float currWidth = GetComponentInParent<Canvas>().GetComponent<RectTransform>().sizeDelta.x;

        GetComponent<RectTransform>().localScale = new Vector3(currWidth / theWidth, currWidth / theWidth, currWidth / theWidth);
    }

    void Update()
    {
        //If resolution changes - we must change button scale
        if(mainCam.pixelRect.height != res.height || mainCam.pixelRect.width != res.width)
        {
            res = mainCam.pixelRect;

            float currWidth = GetComponentInParent<Canvas>().GetComponent<RectTransform>().sizeDelta.x;
            GetComponent<RectTransform>().localScale = new Vector3(currWidth / theWidth, currWidth / theWidth, currWidth / theWidth);
        }
    }

    void OnMouseEnter()
    {
        CoroutineExecutor.instance.Execute(anim);
    }

    void OnMouseExit()
    {
        ResetAnim();
    }

    void OnMouseUpAsButton()
    {
        ResetAnim();
        if(onClick != null)
            onClick();
    }

    void OnDestroy()
    {
        CoroutineExecutor.instance.StopExecution(anim);
    }

    void ResetAnim()
    {
        CoroutineExecutor.instance.StopExecution(anim);
        anim = null;
        anim = buttonAnimation();
        GetComponent<LineRenderer>().material.SetColor("_Color", new Color32(255, 255, 0, 0));
        animating = false;
    }

    IEnumerator buttonAnimation()
    {
        //Debug.Log("Start animation!");
        if (animating)
            yield break;
        GetComponent<LineRenderer>().material.SetColor("_Color", new Color32(255, 255, 0, 0));

        animating = true;
        LineRenderer lr = GetComponent<LineRenderer>();
        while (true)
        {
            float t = 0;
            while(t < 1)
            {
                t += Time.deltaTime * animSpeed;
                lr.material.SetColor("_Color", Color.Lerp(new Color32(255, 255, 0, 0), new Color32(255, 255, 0, 255), t));
                yield return new WaitForEndOfFrame();
            }
            t = 0;

            while (t < 1)
            {
                t += Time.deltaTime * animSpeed;
                lr.material.SetColor("_Color", Color.Lerp(new Color32(255, 255, 0, 255), new Color32(255, 255, 0, 0), t));
                yield return new WaitForEndOfFrame();
            }
            yield return new WaitForEndOfFrame();
        }
    }
}

多数人看起来像这样:

Layer

答案 3 :(得分:0)

我认为,这种方式更为简单

public static void DrawPolygonCollider(PolygonCollider2D collider)
{
    LineRenderer _lr = collider.gameObject.AddComponent<LineRenderer>();
    _lr.startWidth = 0.025f;
    _lr.endWidth = 0.025f;
    _lr.useWorldSpace = false;
    _lr.positionCount = collider.points.Length + 1;
    for (int i = 0; i < collider.points.Length; i++)
    {
        _lr.SetPosition(i,new Vector3(collider.points[i].x,collider.points[i].y));
    }
    _lr.SetPosition(collider.points.Length, new Vector3(collider.points[0].x, collider.points[0].y));
}