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



Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐