项目demo之——翻页
先上图 看效果
分析:
1.分页由shader实现
2.shader的图片类容由截屏功能实现
3.按钮触发功能
有2个cs文件 1个shader组成
代码如下
1.EventTriggerListener.cs //将此代码放在项目中任何地方
using UnityEngine; using System.Collections; using UnityEngine.EventSystems; public class EventTriggerListener : UnityEngine.EventSystems.EventTrigger { public delegate void VoidDelegate(GameObject go); public VoidDelegate onClick; public VoidDelegate onDown; public VoidDelegate onEnter; public VoidDelegate onExit; public VoidDelegate onUp; public VoidDelegate onSelect; public VoidDelegate onUpdateSelect; static public EventTriggerListener Get(GameObject go) { EventTriggerListener listener = go.GetComponent<EventTriggerListener>(); if (listener == null) listener = go.AddComponent<EventTriggerListener>(); return listener; } public override void OnPointerClick(PointerEventData eventData) { if (onClick != null) onClick(gameObject); } public override void OnPointerDown(PointerEventData eventData) { if (onDown != null) onDown(gameObject); } public override void OnPointerEnter(PointerEventData eventData) { if (onEnter != null) onEnter(gameObject); } public override void OnPointerExit(PointerEventData eventData) { if (onExit != null) onExit(gameObject); } public override void OnPointerUp(PointerEventData eventData) { if (onUp != null) onUp(gameObject); } public override void OnSelect(BaseEventData eventData) { if (onSelect != null) onSelect(gameObject); } public override void OnUpdateSelected(BaseEventData eventData) { if (onUpdateSelect != null) onUpdateSelect(gameObject); } }
2.UIMain.cs //将此代码拖到按钮上
using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.EventSystems; using UnityEngine.Events; public class UIMain : MonoBehaviour { Button button; //接屏文件的大小 Rect r = new Rect(0, 0, 1136, 640); //截屏出来的图片 Texture m_Texture; //得到书的renderer组件 Renderer m_Renderer; //控制shader开关的数值 [Range(0, 1)] float time = 0f; //翻页的布尔值,控制updata里的翻页触发 bool flip = false; //翻了第几页 int numberOfpages = 0; //书页目录的物体 Transform book_Catalog; //书页目录物体的缩放值 Vector3 bookBack; //各个程序功能的页面 Transform parent01; Transform parent02; Transform parent03; Transform parent04; Transform parent05; Transform parent06; Transform parent07; Transform parent08; void Start() { book_Catalog = GameObject.Find("book_beimian").GetComponent<Transform>(); m_Renderer = GameObject.Find("Object001").GetComponent<Renderer>(); bookBack = book_Catalog.localScale; button = transform.Find("Button").GetComponent<Button>(); EventTriggerListener.Get(button.gameObject).onClick = OnButtonClick; //程序页面的实例化 parent01 = GameObject.Find("1").GetComponent<Transform>(); parent02 = GameObject.Find("2").GetComponent<Transform>(); parent03 = GameObject.Find("3").GetComponent<Transform>(); parent04 = GameObject.Find("4").GetComponent<Transform>(); parent05 = GameObject.Find("5").GetComponent<Transform>(); parent06 = GameObject.Find("6").GetComponent<Transform>(); parent07 = GameObject.Find("7").GetComponent<Transform>(); parent08 = GameObject.Find("8").GetComponent<Transform>(); } private void OnButtonClick(GameObject go) { //在这里监听按钮的点击事件 if (go == button.gameObject) { if(time ==0) { //Debug.Log("DoSomeThings"); //记录页面 pages(); //得到截屏的图片 m_Texture = CaptureScreen(Camera.main, r); //将截屏图片赋值给book m_Renderer.material.SetTexture("_MainTex", m_Texture); //设置翻页为正 flip = true; } } } //截屏 返回截屏图片 public Texture2D CaptureScreen(Camera c, Rect r) { RenderTexture rt = new RenderTexture((int)r.width, (int)r.height, 0); c.targetTexture = rt; c.Render(); RenderTexture.active = rt; Texture2D screenShot = new Texture2D((int)r.width, (int)r.height, TextureFormat.RGB24, false); screenShot.ReadPixels(r, 0, 0); screenShot.Apply(); c.targetTexture = null; RenderTexture.active = null; GameObject.Destroy(rt); //byte[] bytes = screenShot.EncodeToPNG(); //string filename = Application.dataPath + "/ScreenShot.png"; //System.IO.File.WriteAllBytes(filename, bytes); return screenShot; } void Update() { //得到书目录的物体缩放值 Vector3 s = book_Catalog.localScale; if (time >= 1) { //当翻页完成的时候,将其放大到原来大小 if (s.x <= bookBack.x && s.y <= bookBack.y) { s.x += Time.deltaTime; s.y += Time.deltaTime; book_Catalog.localScale = s; } //将翻页设置为假 flip = false; //当目录缩放到原来大小的时候,将shader中的翻页设置为0 if (s.x >= bookBack.x && s.y >= bookBack.y) time = 0; } if (flip) { //如果翻页为正的是后 //将目录缩小到0大小 if (s.x >= 0 && s.y >= 0) { s.x -= Time.deltaTime; s.y -= Time.deltaTime; book_Catalog.localScale = s; } //然后再开始翻页 time = time + Time.deltaTime; //及时将翻页的进度传递给shader m_Renderer.material.SetFloat("_time01", time); //开始翻页的时候 切换程序页面 if (time > 0.1) { if (numberOfpages == 0) { yemian(parent08, parent01); } if (numberOfpages == 1) { yemian(parent01, parent02); } if (numberOfpages == 2) { yemian(parent02, parent03); } if (numberOfpages == 3) { yemian(parent03, parent04); } if (numberOfpages == 4) { yemian(parent04, parent05); } if (numberOfpages == 5) { yemian(parent05, parent06); } if (numberOfpages == 6) { yemian(parent06, parent07); } if (numberOfpages == 7) { yemian(parent07, parent08); } } } } //记录翻页的页数,每反一页,会+1,+到8的时候 让他从0开始循环 public void pages() { numberOfpages++; if (numberOfpages == 8) { numberOfpages = 0; } } //消失上一页 出现下一页,在update里通过页数来确定上一页与下一页 //输入上一页跟下一页 public void yemian(Transform a,Transform b) { //上一页消失 Renderer[] child_a = a.GetComponentsInChildren<Renderer>(); for (int i = 0; i < child_a.Length; i++) { if (time>=0.2) child_a[i].enabled = false; } //下一页出现 Renderer[] child_b = b.GetComponentsInChildren<Renderer>(); for (int i = 0; i < child_b.Length; i++) { if (time >= 0.2) child_b[i].enabled = true; } } }
3.Book.shader
Shader "Unlit/Book" { Properties { //主贴图,来自截图的贴图 _MainTex ("Texture", 2D) = "white" {} //反面贴图 _BackTex ("BackTex",2D) = "white"{} //翻页的过程 _time01 ("time01",Range(0,1)) = 0 //以uv为中点,调节bookuv大小,来配合截图的贴图 _tilingX ("tilingX",range(0.95,1.05)) = 1 _tilingY ("tilingY",range(0.95,1.05)) = 1 _OffsetX ("OffsetX",range(-0.02,0.02)) = 0 _OffsetY ("OffsetY",range(-0.02,0.02)) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 CGINCLUDE #include "UnityCG.cginc" #define pi 3.1415926 sampler2D _MainTex; sampler2D _BackTex; float4 _MainTex_ST; float _time01; float _tilingX; float _tilingY; float _OffsetX; float _OffsetY; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; //翻页的顶点着色器 v2f vert_flip (appdata v) { float4 vert = v.vertex; float theta = _time01 * pi; float flipCurve = exp(-0.1 * pow(v.vertex.x - 0.5, 2)) * _time01; theta +=flipCurve; vert.x = v.vertex.x * cos(clamp (theta,0,pi)); vert.y = -v.vertex.x * sin(clamp (theta,0,pi))+0.01; v2f o; o.uv = TRANSFORM_TEX(v.uv, _MainTex); vert = o.uv.x<=0.5 ? v.vertex:vert; o.vertex = UnityObjectToClipPos(vert); return o; } //第二页顶点着色器,跟翻页的背面公用 v2f vert_Nex (appdata v) { float4 vert = v.vertex; v2f o; o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.uv.y = o.uv.y; o.vertex = UnityObjectToClipPos(v.vertex); return o; } //翻页的片段 fixed4 frag_flip (v2f i) : SV_Target { i.uv = float2 ((i.uv.x -0.5)* _tilingX +0.5,(i.uv.y-0.5) * _tilingY +0.5 ); i.uv += float2(_OffsetX,_OffsetY); fixed4 col = tex2D(_MainTex, i.uv); return col; } //翻页的背面片段 fixed4 frag_Back (v2f i ) : sv_target { i.uv.x = 1 - i.uv.x; i.uv = float2 ((i.uv.x -0.5)* _tilingX +0.5,(i.uv.y-0.5) * _tilingY +0.5 ); i.uv += float2(_OffsetX,_OffsetY); fixed4 col = tex2D(_BackTex,i.uv); return col; } //第二页的片段 fixed4 frag_Next (v2f i ) : sv_target { i.uv.x = i.uv.x; i.uv = float2 ((i.uv.x -0.5)* _tilingX +0.5,(i.uv.y-0.5) * _tilingY +0.5 ); i.uv += float2(_OffsetX,_OffsetY); fixed4 col = tex2D(_BackTex,i.uv); return col; } ENDCG //第一个pass 翻页 Pass { Cull Back Offset 0, 0 CGPROGRAM #pragma vertex vert_flip #pragma fragment frag_flip ENDCG } //第二个pass 翻页的背面 Pass { Cull Front Offset -1, -1 CGPROGRAM #pragma vertex vert_flip #pragma fragment frag_Back ENDCG } //第三个pass 第二页 Pass { Cull Back Offset 1, 1 CGPROGRAM #pragma vertex vert_Nex #pragma fragment frag_Next ENDCG } } }
项目资源如下:
链接:http://pan.baidu.com/s/1eS1YSrK 密码:j0qu