最近我们的游戏要实现这样一个效果。
即死亡之后,出现一个圆圈,圆圈之外都是黑色的,这个圆圈从屏幕外慢慢减小到人物大小。
复活之后,这个圆圈慢慢变大到人物外面。
一开始想了好多方案最后都pass掉了。
留下了最后的方案,使用Shader完成。
首先准备两张图片。一张纯黑背景。一张白色圆圈。
→←
首先是新建一个shader,将shader拖入Material,将Material拖入纯黑背景。
Shader代码如下。
Shader "Custom/magic" {
Properties {
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Mask("Culling Mask", 2D) = "white"{}
_Cutoff("Alpha cutoff", Range(0,1)) = 0.1
}
SubShader {
Tags { "Quene"="Transparent" }
Lighting Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
AlphaTest GEqual [_Cutoff]
Pass
{
SetTexture [_Mask] {combine texture}
SetTexture [_MainTex] {combine texture,texture-previous}
}
}
FallBack "Diffuse"
}
这段代码可以实现重叠部分透明度变为全透明。
在纯黑背景的Inspect中的Shader的Culling Mask选择为白色圆圈。
重点来了。
怎么样实现重叠处变大变小。
如果你用到过Shader那就应该知道Culling Mask里面的Tiling和Offset并不是Scale和position的意思。具体是什么可以百度一下。
我们要实现这功能就是要在Culling Mask仍然处于Albedo的中心的前提下,变大变小。
根据数学归纳法,我求得了在Tiling变化时候Offset的值以保持Culling Mask仍处于Albedo中心。
Offset.x = -(Tiling.x - 1) / 2;
Offset.y同理。
那么我们只需要在改变Tiling的时候改变Offset那么就可以实现上文提到的圆圈变大变小且中心点处在人物中间。
下面的脚本是我现在游戏过后的死亡和重生脚本。需修改之后才能使用。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Prime31;
using UnityEngine.SceneManagement;
public class Die2 : MonoBehaviour {
public bool inDie;
public Vector2 scale;
public bool Big;
public float scaleX;
public float sishu ;
public float offsetX;
public float tx;
public float r;
public bool ifStart;
public bool inLiving;
public GameObject Black;
public Material BlackMaterial;
Vector3 saved_position;
void Start () {
Black = GameObject.Find ("background");//background是黑色背景
inDie = false;
Big = true;
sishu = 0.1f;
tx = 20.48f;
r = 10f;
ifStart = false;
Black.transform.localScale = new Vector3 (0, 0, 0);
BlackMaterial = Black.GetComponent ().material;
inLiving = false;
}
void Update () {
if(inDie)
{
scale = BlackMaterial.GetTextureScale ("_Mask");
offsetX = BlackMaterial.GetTextureOffset ("_Mask").x;
scaleX = scale.x;
if (scale.x > 80) {
BlackMaterial.SetTextureOffset ("_Mask", new Vector2 (0, 0));
AfterDie ();
return;
}
scaleX = Mathf.Lerp (scaleX, 100f, sishu);
offsetX = -(scaleX - 1) / 2;
BlackMaterial.SetTextureOffset ("_Mask", new Vector2 (offsetX, offsetX));
BlackMaterial.SetTextureScale ("_Mask", new Vector2 (scaleX, scaleX));
}
else if(inLiving)
{
scale = BlackMaterial.GetTextureScale ("_Mask");
offsetX = BlackMaterial.GetTextureOffset ("_Mask").x;
scaleX = scale.x;
if (scale.x < 0) {
ifStart = false;
//gameObject.transform.localScale = new Vector3 (0, 0, 0);
scaleX = 1;
offsetX = -(scaleX - 1) / 2;
BlackMaterial.SetTextureOffset ("_Mask", new Vector2 (offsetX, offsetX));
BlackMaterial.SetTextureScale ("_Mask", new Vector2 (scaleX, scaleX));
AfterLiving ();
return;
}
scaleX = Mathf.Lerp (scaleX, -1f, sishu);
offsetX = -(scaleX - 1) / 2;
BlackMaterial.SetTextureOffset ("_Mask", new Vector2 (offsetX, offsetX));
BlackMaterial.SetTextureScale ("_Mask", new Vector2 (scaleX, scaleX));
}
}
void OnTriggerEnter2D(Collider2D other) {
if(other.gameObject.transform.tag == "Save")
{
saved_position = other.gameObject.transform.position;
other.GetComponent ().color = new Color (255, 0, 0);
}
if (other.gameObject.transform.tag == "Finish") {
if(!inDie)
{
GetComponent ().move (new Vector3 (0, 0, 0));
inDie = true;
Black.transform.localScale = new Vector3 (4, 4, 4);
scaleX = 1;
offsetX = 0;
BlackMaterial.SetTextureOffset ("_Mask", new Vector2 (offsetX, offsetX));
BlackMaterial.SetTextureScale ("_Mask", new Vector2 (scaleX, scaleX));}
}
}
void AfterDie()
{
inDie = false;
inLiving = true;
this.transform.position = saved_position;
GetComponent ().Initialization ();
}
void AfterLiving()
{
inLiving = false;
inDie = false;
Black.transform.localScale = new Vector3 (0, 0, 0);
}
}
GitHub:
https://github.com/TaurusGGBOY
CSDN:
https://blog.csdn.net/q378992971
微信公众号:
GameOldMemory
知乎:zhihu.com/people/gao-guo-bin-34