我的问题是标题。我和团结一起玩回到学校,我决定做一个小风险类型的游戏。
基本上我有我的地图,当我点击我的一个地区(我有一个多边形对撞机周围,附加一个点击方法,目前只是切换一个小盒子精灵测试)我想要突出我选择的领域周围的边缘(多边形对撞机覆盖的女巫的边缘)。所以我想知道是否有可能根据对撞机制作高光效果,或类似的东西。
我目前的计划是将所有地区的边缘Photoshop变成精灵,然后像测试精灵一样切换它们以创造效果,但如果我能用更简单的时间有效地完成它,那就太棒了!
如果可以的话,感谢您的帮助,并询问您是否需要更多信息!
答案 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)
如何执行此操作的步骤:
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);
功能可让您在调用时提供选项,例如设置size
和color
。
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();
}
}
}
多数人看起来像这样:
答案 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));
}