<aside> <img src="/icons/robot_gray.svg" alt="/icons/robot_gray.svg" width="40px" /> 本章重點: 如何在Unity Shader中應用Time

</aside>

Unity Shader中的內置時間變量

名稱 類型 描述
_Time float4 t是自該場景加載開始所經過的時間,4個分量的值分別是(t/20, t, 2t, 3t)
_SinTime float4 t是時間的正弦值,4個分量的值分別是(t/8, t/4, t/2, t)
_CosTime float4 t是時間的余弦值,4個分量的值分別是(t/8, t/4, t/2, t)
unity_DeltaTime float4 dt是時間增量,4個分量的值分別是(dt, 1/dt, smoothDt, 1/smoothDt)

可以看得出,都是佔用了32位的值。這與顯卡的構造有關(SIMD),可以自行查詢相關的資料。

紋理動畫 - 幀動畫

<aside> <img src="/icons/drafts_gray.svg" alt="/icons/drafts_gray.svg" width="40px" /> 書中所給的圖片的第一行是火焰已經快燒完的,在課外練習中有修正後的版本

</aside>

代碼可能不好理解,所以這裏一步一步地說明。

需要預設一些參數:

  1. 以1秒為單位,向右移動1格
  2. 當水平方向沒有格能移動,回到最左邊的格,並往上移一格
  3. Texture要設置成Repeat形式,這樣才能不斷地重覆

流程

  1. 首先是如何對某一格進行取樣,只需要除以水平方向和垂直方向的數量便可,相當於將[0, 1]範圍映射到[0, 1/8]的範圍中

    uv.x /= _HorizontalAmount;
    uv.y /= _VerticalAmount;
    
  2. 然後是移動「取樣格」。首先先忽略_Speed的影響。已知,1秒會移動一次。所以使用floor向下取整限制只有在經過了1秒後才會移動,所以time相當於是移動的總次數。row指的是第x行,而column指的是第x列。通過將time / 水平數量,得到垂直方向總共移動多少次,再將總次數減去已移動的次數,就是水平方向的移動次數。最後將得到的結果與原uv相加便可。

    float time = floor (_Time.y);
    float row = floor (time / _HorizontalAmount);
    float column = time - row * _HorizontalAmount;
    half2 uv = i.uv + half2 (column, -row);
    

    例如: 經過了30.5秒,通過向下取整,得到30秒,所以總共移動了30格。30/8 = 3.75,即row = 3,所以column = 6。也就是說,水平方向移動6次,垂直方向移動3次。可以得到

    注意: 垂直方向是往下的,而因為Texture是Repeat,所以會從上方開始往下移動。

    注意: 垂直方向是往下的,而因為Texture是Repeat,所以會從上方開始往下移動。

    通過在Shader中將time設置為30,可以得到這樣的圖片

    Untitled

  3. 將速度因數應用,相當於提升「取樣格」的移動速度而已。

    float time = floor (_Time.y * _Speed);
    

<aside> <img src="/icons/drafts_gray.svg" alt="/icons/drafts_gray.svg" width="40px" /> 關鍵在對紋理進行均勻的等分,得到格子,並在格子中取樣。這一步能理解的話,那麼其它就不是問題了。

</aside>