0

我的问题如标题所示。我正在和团结一起玩重新回到学校,我决定制作一个风险类型的小游戏。

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

我目前的计划是将所有区域的边缘用 Photoshop 制作成精灵,然后像测试精灵一样切换它们以创建效果,但如果我能以一种更简单、省时的方式做到这一点,那就太好了!

在此处输入图像描述

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

4

4 回答 4

2

在此处输入图像描述

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

如何执行此操作的步骤:

1LineRenderer .从代码中创建新的。

2 .Assign Material给新的Line Renderer,设置宽度和颜色。

3 .Get 中的PolygonCollider2D其中返回点的数组PolygonCollider2D

4 .循环点并使用函数将每个点从本地空间转换为世界空间TransformPoint..

5SetVertexCount .将LineRenderer的 设置Length为点的 加 1。我们需要额外的 1 来关闭我们正在绘制的内容。

画线

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

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

由于这是 2D,您可能需要修改 pointsArray 的 Z 轴以确保该对象显示在每个 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()
    {

    }
}
于 2016-08-26T18:55:54.987 回答
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);

希望这足够接近!

于 2016-08-25T20:42:27.750 回答
0

这是我使用的解决方案。它使用 Line Renderer,女巫在 Unity 5.5 中最终会变得漂亮。

我得到了用作按钮的对象。它有 PoligonCollider2D、LineRenderer 和这个 sript。此外,线渲染器必须在分辨率更改后重新绘制自身。所以我以特定的分辨率配置我的 poligon 对撞机,您可以在游戏窗口中进行配置。在我的脚本中,我使用 689*500,即 16/9 分辨率。Canvas 是 Screen Space - Camera 并且具有 1.7777778 值的 Aspect Ratio Fitter。

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();
        }
    }
}

这一切看起来像这样:

例子

于 2016-10-31T20:04:13.297 回答
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));
}
于 2020-05-07T13:55:11.620 回答