unity 打字机变色效果
·
unity 打字机变色效果
实现效果

工程文件下载
实现难点
打印文字的最后一个字的颜色是与前面文字的颜色不同的,而且打印后逐渐变为前面字的颜色。
实现思路
考虑到unity的text组件的颜色是整体修改的,所以改使用shader的位置判断修改文字颜色。
shader源码
Shader "Unlit/TextColor"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Text Color", Color) = (1,1,1,1)
_Colornew("new Color", Color) = (1,1,1,1)
_X("x",Range(-1920,1920)) = 0.1
_Y("y",Range(-1920,1920)) = 0.1
_T("time",Float) = 0
}
SubShader
{
Tags {
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
}
LOD 100
Lighting Off Cull Off ZWrite On Fog { Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
fixed4 color : COLOR;
float4 texcoord : TEXCOORD0;
//UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
fixed4 colornew : COLORN;
float3 worldPos:TEXCOORD1;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform float4 _MainTex_TexelSize;
uniform fixed4 _Color;
uniform fixed4 _Colornew;
uniform float _X;
uniform float _Y;
uniform float _T;
v2f vert(appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color * _Color;
o.colornew = _Colornew;
step(v.texcoord, v.vertex.xy);
o.texcoord = TRANSFORM_TEX(v.texcoord.xy,_MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col ;
if (i.worldPos.x < _X ||i.worldPos.y > _Y)
{
col = i.color;
col.a = tex2D(_MainTex, i.texcoord).a;
}
else
{
col = lerp( i.colornew, i.color, _T);
col.a = tex2D(_MainTex, i.texcoord).a;
}
return col;
}
ENDCG
}
}
}
#代码
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class Typewriter : MonoBehaviour
{
public float TextTime;
public float ColorTime;
Text selfText;
Material material;
Vector2 size;
Vector3 vec;
void Start()
{
//设置锚点
gameObject.GetComponent<RectTransform>().pivot = new Vector2(0.5f, 1);
//读取文件相对位置
vec = gameObject.GetComponent<RectTransform>().localPosition;
selfText = gameObject.GetComponent<Text>();
material = selfText.material;
size = gameObject.GetComponent<RectTransform>().sizeDelta;
gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(size.x, selfText.preferredHeight);
DoStringRead(selfText.text, TextTime, SetText);
}
/// <summary>
/// 设置文字及文字颜色
/// </summary>
/// <param name="Str"></param>
void SetText(String Str)
{
selfText.text = Str;
float layer = Mathf.Ceil( selfText.preferredWidth / size.x) ;
float layerHigh = Mathf.Floor(selfText.preferredHeight / layer);
Debug.Log(layer + "," + layerHigh);
material.SetFloat("_Y", layerHigh - layerHigh*(layer)+ vec.y);
material.SetFloat("_X", selfText.preferredWidth-(size.x* (layer-1)) - (size.x / 2 + selfText.fontSize) + vec.x);
DoTime(ColorTime, (float t)=>material.SetFloat("_T", t));
}
/// <summary>
/// 顺序打印
/// </summary>
/// <param name="stringInfo"></param>
/// <param name="time"></param>
/// <param name="action"></param>
/// <param name="id"></param>
void DoStringRead(string stringInfo, float time, Action<string> action, string id = null)
{
Char[] stringInfos = stringInfo.ToCharArray();
IEnumerator coroutine;
coroutine = DoStringReadIE(stringInfos, time, action);
StartCoroutine(coroutine);
}
/// <summary>
/// 颜色渐变
/// </summary>
/// <param name="time"></param>
/// <param name="action"></param>
void DoTime(float time, Action<float> action)
{
IEnumerator coroutine;
coroutine = DoTimeIE(time, action);
StartCoroutine(coroutine);
}
IEnumerator DoStringReadIE(Char[] stringInfos, float time, Action<string> action = null)
{
float count = 0;
float stringCount = stringInfos.Length;
float newTime = time / stringCount;
while (count <= stringCount)
{
yield return new WaitForSeconds(newTime);
string infos = "";
for (int i = 0; i < count; i++)
{
infos += stringInfos[i];
}
action(infos);
count++;
}
}
IEnumerator DoTimeIE(float time, Action<float> action = null)
{
float t = 0;
while (t < 1)
{
t += Time.deltaTime / time;
if (action != null)
{
action(t);
}
t = t > 1 ? 1 : t;
yield return null;
}
}
}
更多推荐
所有评论(0)