ChunkDisappearImage-一個以矩形爲單位的圖片消失分解效果

效果



使用

1.將ChunkDisappearImage掛在一個空GameObject上。
2.將ChunkDisappearImage的Material設爲ChunkDisappearImageMaterial。
3.設置RectTransform的寬、高、縮放、旋轉等參數。設置ChunkDisappearImage的參數。git

參數

Speed: 小方塊移動的速度。
TargetX,TargetY: 每一個小方塊移動的終點座標。
SubRectX,SubRectY: 每一個小方塊的長寬。
Interval: 每一個小方塊開始移動時間的間隔。
SpeedArg: 距離越遠的方塊是否運行越快,_SpeedArg爲1時,全部方塊運行速度基本相同,值越小,距離越遠的方塊運行的越快。
ps:目標點的座標,小方塊的寬高都是Image對象爲父節點的本地座標。github

實現

簡介

實現主要分爲三個步驟:
1.修改image的mesh。
2.將與運動相關的參數傳入shader中。
3.在移動結束後將mesh恢復爲普通的image的shader。
canvas

實現細節

mesh的拆分

1.Image經過OnPopulateMesh函數構建對應的mesh,因此咱們經過重寫Image的OnPopulateMesh來對mesh進行構建。

Image的默認mesh:

拆分後的mesh: 以拆分爲四塊爲例

將mesh拆分爲不少個小矩形後,還得想辦法告訴shader每一個頂點是屬於那個矩形的,才能以此爲依據進行矩形的移動。app

2.如何告訴shader每一個頂點是屬於哪一個矩形的。

public partial struct UIVertex
{
    public Vector3 position;
    public Vector3 normal;
    public Vector4 tangent;
    public Color32 color;
    public Vector2 uv0;
    public Vector2 uv1;
    public Vector2 uv2;
    public Vector2 uv3;

能夠看下描述一個UI頂點的結構體中都包含了哪些字段,UGUI中只用到了position,color,uv0這三個字段。
這表明咱們可使用剩餘的字段傳咱們須要的額外信息,這裏選擇使用uv1字段將每一個矩形的左下角的點做爲矩形的位置信息傳入shader,在shader中,以此爲基礎進行小矩形塊的移動。
注意:
①不能用normal和tangent,由於UGUI在渲染時,傳入shader中的position不是傳入VertexHelper時的原始值,而是該點在根canvas上的座標,同理,normal,tangent也作了相應的變換。不是原始值了。
因此在傳額外信息的時候要用uv一、uv二、uv3字段,這三個字段不會隨點的移動、旋轉、縮放而改變。
②因爲unity高版本在ugui渲染時作了優化,在默認狀況下只會將position、color、uv0三個字段傳入shader,因此須要手動將uv1設爲生效才行。
函數

image本地座標到根canvas座標的模型矩陣的計算

mLocalToCanvas = canvas.rootCanvas.transform.localToWorldMatrix.inverse * transform.localToWorldMatrix;

image的模型矩陣:

canvas的模型矩陣:

因爲矩陣知足結合律,因此用用canvas的模型矩陣的逆乘以image的模型矩陣會將canvas的模型矩陣消掉,也就是image座標->canvas座標的模型矩陣:

用這個矩陣乘上image上的本地座標就能夠算出對應的canvas上的座標。優化

開始時間和結束時間的計算

開始時間
分兩種狀況:
①當目標點在圖片內時,不去算準確的起始時間,直接設置爲0。
②當目標點在圖片外時,最近點必定是四個頂點之一。遍歷四個頂點,計算一下離目標點最近的方塊開始運動時的_Delta值,即f第一次不爲0的時候
結束時間
計算一下最遠點的f爲1的狀況便可,因爲距離目標點最遠的點必定是四個頂點之一,因此枚舉四個頂點便可。ui

shader的重寫

咱們要改動Image默認的shader的頂點着色器來實現每一個頂點的位移和alpha值的下降。
咱們選擇5.37f1的UGUI默認shader,UI-Default.shader進行修改,這個在unity官網就能夠下到。
code

注意:

在Unity高版本打開低版本的shader時,會對一些函數作替換,如在2018.2打開5.37f1的shader時,會對以下語句進行修改。orm

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

此demo中使用的是2018.2版本的unity,因此在低版本使用時要把這句話改回去,否則會報錯。對象

頂點的移動公式:

//計算該方塊到目標點的距離,以此爲標準做爲每一個方塊移動時間的延遲
float distance = length(target.xyz - leftBottom.xyz);
//距離越遠的方塊是否運行越快,_SpeedArg爲1時,全部方塊運行速度大體相同,值越小,距離越遠的方塊運行的越快
float tempDis = 1 + distance * _SpeedArg;
float f = clamp((_Delta - distance * _Interval) / tempDis, 0, 1);

根據f在0-1之間的變化,來控制方塊在起點到終點之間的移動和alpha值的變化。
①distance * _Interval保證每一個距終點距離不一樣方塊之間的開始移動時間會有一個間隔。
②tempDis能夠控制不一樣距離方塊之間的速度比。

小結

原理其實並不難,主要只有兩部分:改mesh,改shader。就是一些座標的轉換、開始結束時間的控制、版本的兼容性比較麻煩。
在把整個流程跑通一次以後,就會對流程有一個較爲全面的認識,下次作2D或是3D的一些效果思路也也會更廣一些。

代碼連接:https://github.com/blueberryzzz/UIAndShader/tree/master/UIAndShader/Assets/ChunkDisappearImage

相關文章
相關標籤/搜索