Java 複製檔案的方式

方法一: 使用 java.io 的 FileInputStream 讀取,在使用 FileOutputStream 寫入。這種方式使用 byte stream 直接讀取來源檔案內容,在寫入到目標檔案。比 Files.copy 慢。

1
2
3
4
5
6
7
8
9
FileInputStream fis = new FileInputStream("source.txt");
FileOutputStream fos = new FileOutputStream("destination.txt");
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
fis.close();
fos.close();

方法二: 使用 java.nio 的 transferTo 讀取,在使用 transferFrom 寫入。這種方式可以直接在 FileChannel 中傳輸資料。它可以快速的將資料從一個 channel 傳輸到另外一個 channel ,而不需要在 User space 與 Kernal space 進行資料複製,是一種實現 zero copy 的複製方式。但是在某些作業系統中, transferTo 可能會限制傳輸的最大 Byte ,因此在使用時,可能需要進行分段傳輸。

1
2
3
4
5
FileChannel sourceChannel = new FileInputStream("source.txt").getChannel();
FileChannel destChannel = new FileOutputStream("destination.txt").getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), destChannel);
sourceChannel.close();
destChannel.close();

方法三: 使用 java.nio 的 Files.copy 。java NIO 提供的一種高級操作方式,但是它本身不實現 zero copy 技術

1
2
3
Path sourcePath = Paths.get("source.txt");
Path destinationPath = Paths.get("destination.txt");
Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);

注意:以上的操作都沒有使用 try finally 或是 try-with-resources 關閉資源,正確的使用需要關閉資源才不會造成 Memory leak

1
2
3
4
5
6
7
8
9
10
try (FileInputStream fis = new FileInputStream("source.txt");
FileOutputStream fos = new FileOutputStream("destination.txt")) {
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}

How to use Cursor AI in Unity

在 Mac 的 Unity 中如何使用 Cursor AI ?
以下記載如何在 Mac 的 Unity 中設定 Cursor AI

  1. 在 Unity 編輯器中,找到 Windows -> Package Manager

  2. 點擊 + 展開選單,並找到 Add package from git URL 並選擇,在輸入 https://github.com/boxqkrtm/com.unity.ide.cursor.git , 以安裝 Cursor Editor

  3. 接著到 https://www.cursor.com/ 註冊帳號並下載 Cusor Editor 安裝。

  4. 然後到 Preferences -> External Tools -> External Script Editor ,選擇安裝的 Cursor

  5. 至此,便可以在編寫程式碼的時候,使用 Cursor AI 了。

  • 按下 + L 可以開啟 AI 互動,在這邊你可以向AI闡述你的問題,讓它生成相關的程式碼

  • 按下 + K 在這邊你可以向AI闡述你的需求,讓它在選中的段落為你產生程式碼。

Unity 2D Liquid

以下將介紹如何使用 Shader , Texture , 以及 Camera 來在 2D 中建立液體(Liquid)效果。

建立互動物件

  1. 首先建立液體:建立一個 Circle Sprite 並添加 CircleCollider2D 與 Rigidbody2D ,並命名為 Liquid 。
  2. 建立一個 Empty Game Object 命名為 Liquids , 並在其中將剛剛建立的 Liquid 複製多份。
  3. 建立牆體:建立一個 Square Sprite 並加入 BoxCollider2D ,並命名為 Wall 。
  4. 建立一個 Empty Game Object 命名為 Walls , 並在其中將剛剛建立的 Wall 複製多份,排列為一個可以承裝物體的凹型。
  5. 建立一個 Liquids Layer
  6. 建立一個 LiquidCamera 並更改以下屬性
    • Clear Flags : Solid Color
    • Background : 黑色
    • Culling Mask : 設為剛剛建立的 Liquids Layer
    • Projection : 更改為 Orthographic
  7. 建立一個 Textures 資料夾,在其中建立一個 Render Texture 並命名為 LiquidTexture
  8. 將剛剛建立的 LiquidTexture 設定到 LiquidCamera 的 Target Texture
  9. 安裝 Shader Graph
  10. 建立一個 Shaders 資料夾,在其中建立一個 Unlit Shader Graph 並命名為 LiquidShaderGraph
  11. 使用滑鼠左鍵點擊剛剛建立的 LiquidShaderGraph 打開 Shader Graph Editor
  12. 滑鼠在 + 按鈕上面點擊一下展開選單,找到 Texture 2D 並點擊建立,並命名為 MainTex
  13. 點擊剛剛建立的 MainTex 在右側的 Graph Inspector 中找到 Default 並將 LiquidTexture 設定到這個 Default
  14. 使用滑鼠左鍵按住 MainTex 並拖拉到中央,如下圖
  15. 在空白處按下滑鼠右鍵找到 Create Node 並按下,在 Create Node 選單中找到 Sample Texture 2D 並按下建立一個 Sample Texture 2D Node
  16. 使用滑鼠左鍵將 MainTex 的接點拖拉到剛剛建立的 Sample Texture 2D Node
  17. 建立一個 Float 並命名為 Tickness
  18. 建立一個 Step Node ,將剛剛建立的 Thickness 連接到 Edge ,將 Sample Texture 2D 的 Alpha (A) 連接到 In
  19. 建立一個 Color 並命名為 Color , Default 設為藍色
  20. 建立一個 Multiply Node 並將 Step Node 的 Out 連接到 A ; 將剛剛建立的 Color 連接到 B
  21. 找到 Fragment Node ,將它的 Suface Type 設為 Transparent ,將 Step Node 的 Out 連接到 Fragment 的 Alpha ; 將 Multiply 的 Out 連接到 Base Color
  22. 最後按下 Save Asset 把它儲存
  23. 建立一個 Materials 資料夾,並在其中建立 Material 並命名為 LiquidMaterial
  24. 將剛剛建立的 LiquidMaterial 的 Shader 設為之前建立的 LiquidShaderGraph 並設定它的顏色為藍色
  25. 在 LiquidCamera 之下建立一個 Quad ,將它的 Z Position 設為 10 ,它的 Materials 設為 LiquidMaterial
  26. 最後觀看結果

Reference:

粒子系統的 Color by Speed

此模組可以根據粒子的速度(每秒的距離單位)來改變顏色

屬性 說明
Color 根據速度範圍定義的粒子顏色漸變。
Speed Range 此屬性用來映射顏色漸變(速度在範圍外的將映射到漸變的端點)。

燃燒或發光的粒子(如火花)在快速通過空氣時通常會燃燒得更亮(例如,當火花暴露在更多氧氣中時),但隨著速度減慢會稍微變暗。為了模擬這一點,你可以使用按速度變化顏色功能(Color By Speed),將漸變色設置為速度範圍的高端為白色,低端為紅色(在火花的例子中,更快的粒子會顯示為白色,而較慢的粒子則顯示為紅色)。

Color over Lifetime

此模組指定粒子在生命週期中要如何要如何顯示它的顏色與透明度。

屬性 說明
Color 粒子在其生命週期內的顏色漸變。漸變條最左邊的點表示粒子生命的開始,最右邊的點表示粒子生命的結束。

粒子會隨著時間變化顏色,例如,白熱的火花在穿過空氣時會冷卻,而魔法咒語可能會爆發出彩虹般的顏色。同樣重要的是透明度的變化。粒子在其生命週期結束時通常會燃燒殆盡、逐漸消失或散佈(例如,熱火花、煙火和煙霧粒子),而一個簡單的逐漸減少的漸變可以產生這種效果。

當同時使用起始顏色屬性時,此模組會將兩種顏色相乘,得到最終的粒子顏色。

粒子系統的 Lifetime by Emitter Speed

Lifetime by Emitter Speed 模組根據發射器的速度來控制每個粒子的初始壽命。它會將粒子的初始壽命乘以一個取決於發射物體速度的值。對於大多數粒子系統來說,這個值是來自遊戲物體的速度,但對於子發射器(sub-emitter)來說,速度來自於生成該子發射器粒子的父粒子。

屬性 說明
Multiplier 粒子的初始壽命會乘上一個倍數。這個模組根據你設置的曲線模式以不同方式使用這個倍數。曲線模式包括:
Constant :使用固定倍數值。這種模式會忽略 Speed Range 屬性。
Curve : 根據發射器的速度,將其映射到介於 0 和 1 之間的值,然後使用正規化為這個曲線取樣。
Random Between Two Constants :為每個粒子設置一個介於兩個值之間的隨機倍數。這種模式會忽略 Speed Range 屬性。
Random Between Two Curves :根據發射器的速度,將其映射到介於 0 和 1 之間的值,然後使用正規化為這些曲線取樣。對於每個粒子,模組會將倍數設置為這兩個樣本之間的隨機值。
Speed Range 粒子系統將發射器速度映射到 Multiplier(倍數)曲線上的最小值和最大值。如果發射器的速度等於第一個值,那麼倍數就是曲線開始時的值。如果發射器的速度等於第二個值,那麼倍數就是曲線末端的值。這個屬性僅在 倍數(Multiplier)的曲線模式設置為曲線 CurveRandom Between Two Curves 時才有關聯。

Reference:

粒子系統的 Force over Lifetime

在此模組中指定的力量(如風或吸引力)讓粒子加速。

屬性 說明
X, Y, Z 在 X、Y 和 Z 軸上應用於每個粒子的力量。
Space 選擇力量是應用於局部空間(Local)還是世界空間(World)。
Randomize 當使用 Random Between Two ConstantsRandom Between Two Curves 模式時,系統會在每一幀內從定義的範圍中選擇新的力的方向讓粒子的運動變得更加混亂和不規則。

在流體(Fluids)的運動中,常常會受到外力的影響。例如,煙霧從火源上升時,會因為周圍的熱空氣而稍微加速。通過使用曲線來控制粒子在其生命周期中的力量,可以實現微妙的效果。以之前的例子為例,煙霧最初會向上加速,但隨著上升的空氣逐漸變涼,力量會減弱。火焰產生的濃煙可能會在最初加速,然後隨著擴散變慢,甚至如果持續很長時間,可能會開始向下落。

Reference:

粒子系統的 Inherit Velocity

使用這個模組在子發射器(subemitters)上。父系統中的每個粒子都可以在子發射器中產生粒子。此模組讀取來自父粒子的速度,並控制子發射器粒子的速度如何隨著時間對該速度作出反應。

屬性 說明
Mode 指定發射器速度如何應用於粒子。
Current :發射器(emitter)目前的速度將會在每一幀中應用到所有粒子。例如,目前的發射器速度減慢,則所有粒子也會跟著減慢。
Initial :發射器的速度會在每個粒子生成時應用一次。之後發射器速度的任何變化都不會影響已經生成的粒子。
Multiplier 設定粒子應繼承的發射器速度的比例。

這個模組適合從移動物體中發射粒子,例如從車輛產生的塵土,火箭的煙霧,蒸汽火車煙囪中的蒸汽,或任何需要粒子在初始階段以其來源物體的速度的百分比移動的情況。這個模組只在主模組中的 Simulation Space 設為 World 時才會對粒子產生影響。

也可以使用曲線讓效果隨時間變化。例如,你可以對新建立的粒子施加強的吸引力,隨時間減少。這對於蒸汽火車的煙霧會很有用,煙霧會隨時間慢慢漂移,停止並跟隨它所排放的火車。

Unity 以兩種方式計算發射器的速度,可以在主模組中的 Emitter Velocity 屬性設定要使用的計算方式:

  • 基於附加的 Rigidbody 組件的速度
  • 基於粒子系統的 Transform 組件在目前幀中移動的距離

粒子系統的 Noise module

Noise module 為粒子運動添加湍流(turbulence)效果。預設中不會啟用這個模組。

屬性 說明
Separate Axes 對粒子效果進行細緻的調整,以便在 X、Y 和 Z 軸上分別應用不同的強度和重映射值。
Strength 一條曲線(curve)來定義噪聲效果(noise effect)在粒子整個生命週期中的強度。越高的值會使粒子移動得更快、更遠。
Frequency 此屬性控制了粒子改變運動方向的頻率以及改變方向的劇烈程度,較低的值會產生柔和(soft)、平滑(smooth)的噪聲(noise),較高的值會產生快速變化的噪聲。
Scroll Speed 此屬性讓粒子隨著時間運動的更加不可預測和不規則。值越高粒子移動越不穩定。
Damping 啟用此屬性後,強度與頻率成正比。
Octaves 用於指定生成最終噪聲值的重疊噪聲層數。使用更多層會產生更豐富、更複雜的噪聲,但會顯著增加性能成本。
Octave Multiplier Octaves 啟用時才可用。對於每個額外的噪聲層(noise layer),將強度按此比例減少。
Octave Scale Octaves啟用時才可用。使用此屬性來調整每個額外的噪聲層的頻率。
Quality 較低的 Quality ,可以減少效能消耗,但是也會影響噪聲(noise)的視覺效果。
Remap 將最終的噪聲值重新映射到不同的範圍內。
Remap Curve Remap 啟用時才可用。此屬性為描述如何將最終噪聲值轉換為不同範圍的曲線。例如,可以使用此曲線來選擇噪聲場中的較低範圍並忽略較高範圍,透過建造一個從高開始並在零處結束的曲線來實現。
Position Amount 控制噪聲對粒子位置影響的倍數。
Rotation Amount 控制噪聲對粒子旋轉影響的倍數(以每秒度數為單位)。
Size Amount 控制噪聲對粒子大小影響的倍數。

可以用強烈的高頻噪聲來模擬火星的運動,而使用柔和的低頻噪聲則更適合模擬煙霧效果。
噪聲(Noise)演算法基於 Curl Noise,內部使用多個 Perlin Noise 樣本(Sample)來建立最終的噪聲場。

Reference:

粒子系統的 Velocity over Lifetime module

Velocity over Lifetime 模組讓你可以在粒子生命週期中控制粒子的速度。預設中不會啟用這個模組。

屬性 說明
Linear X, Y, Z 粒子在 X,Y 與 Z 軸(axe) 上直線運動速度(Linear velocity)
Space 指定線性 X、Y、Z 軸是指本地空間(Local)還是世界空間(World)。
Orbital X, Y, Z 粒子圍繞 X、Y 和 Z 軸的軌道速度(Orbital velocity)。
Offset X, Y, Z 繞軌粒子的軌道中心位置。
Radial 粒子朝向或遠離中心位置的徑向速度(Radial velocity)。
Speed Modifier 對粒子沿著/圍繞其當前移動方向的速度應用一個倍數。

要建立在特定方向上漂移的粒子,可以使用 Linear X, Y, Z 曲線(curve)模式。

要建立圍繞中心位置旋轉的粒子效果,請使用 Orbital X, Y, Z 。此外,可以使用 Radial 將粒子推向或遠離中心位置。通過使用 Offset X, Y, Z ,您可以為每個粒子定義自定義的旋轉中心。

您還可以使用此模組來調整粒子系統中粒子的速度,而不影響它們的方向,只需將上述所有值保持為零,僅修改 Speed Modifier 即可。

Reference: