Unity in Rust
Rust言語をUnityから呼び出してテクスチャ画像を表示するデモを見つけましたので、試してみました。
参考動画)
難易度はかなり高いですが、このしくみはいろいろと活用できそうです。
インストール)
※コマンドは環境によってかわるため参考までに(Ubuntu20.04/WSL)
git clone https://github.com/keijiro/UnityRustPlugin.git
sudo apt install gcc-mingw-w64-x86-64
rustup target add x86_64-pc-windows-gnu
cd UnityRustPluting/Plugins
./build.sh
このままUnityで開いただけでは何も表示しないので、Test.csをオブジェクトのマッピングします。
ここではCubeとShpere、2つ使用しました。
実行画面
ここまで簡単に動作確認ができるのはありがたいです。
肝心のC#からRustへの呼び出し部分のI/Fを確認してみます。
Assets/Test.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using UnityEngine; using System.Runtime.InteropServices; public class Test : MonoBehaviour { #if !UNITY_EDITOR && (UNITY_IOS || UNITY_WEBGL) [DllImport("__Internal")] #else [DllImport("mandelbrot")] #endif static extern void generate_image([Out] Color32[] buffer, int width, int height); const int Size = 512; void Start() { var startTime = Time.realtimeSinceStartup; var pixels = new Color32[Size * Size]; generate_image(pixels, Size, Size); var endTime = Time.realtimeSinceStartup; Debug.Log("execution time = " + (endTime - startTime)); var texture = new Texture2D(Size, Size); texture.wrapMode = TextureWrapMode.Clamp; texture.SetPixels32(pixels); texture.Apply(); GetComponent<Renderer>().material.mainTexture = texture; } void Update() => transform.localRotation = Quaternion.Euler(16.6f * Time.time, 30.8f * Time.time, 0); } |
Plugin/src/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
use num::complex::Complex; fn mandelbrot(px: i32, py: i32, width: i32, height: i32) -> i32 { let x = (px as f32) / (width as f32) * 2.5 - 2.0; let y = (py as f32) / (height as f32) * 2.0 - 1.0; let c = Complex::new(x, y); let mut z = Complex::new(0.0, 0.0); let mut i = 0; while z.norm_sqr() < 4.0 { z = z * z + c; i += 1; if i == 300 { return 0; } } i } #[no_mangle] pub unsafe extern "C" fn generate_image(buffer: *mut u8, width: i32, height: i32) { let data = std::slice::from_raw_parts_mut(buffer, (width * height * 4) as usize); let mut offs = 0; for y in 0..height { for x in 0..width { let c = mandelbrot(x, y, width, height); data[offs + 0] = (c * 31) as u8; data[offs + 1] = (c * 37) as u8; data[offs + 2] = (c * 41) as u8; data[offs + 3] = 255; offs += 4; } } } |
generate_image関数を呼び出しで、Cを経由するグルーコードが書かれています。
(Haskellとかもそうでした。http://bitlife.me/archives/tag/haskell)
こういうの調べると大変なんですよね。
I/Fの書き方がわかればいろいろと応用ができます。
別にRustなんかつかわずC#でみんな書けばいいのでは、という声が聞こえてきそうですが、外部の言語を呼び出せるとその言語でしかないライブラリが活用できるから便利なのです。
既存の機能を呼びだしりするときにこういうテクニックはよく使われます。
今回、どうしても残しておきたかったので引用させていただきました。
すばらしいデモ、ありがとうございました!
Category: 3D