- 投稿日:2020-07-14T17:28:49+09:00
【cluster】unity高速化【unityアクセラレータ、compressアセット】
- 要は、unityを細かいところで高速化するための記事です。
- clusterのワールドアップロードがすんごい時間かかるのは、windowsビルド、Macビルド、iOSビルド、アンドロイドビルドをすべて行っているため。
- そのため、これらの工程内の無駄を省くいくつかのオプションがあるというお話が、この記事。
Unity Accelerator
Speed up your team with the Unity Accelerator
日本語訳
- コラボレート機能と合わせるとなんかすごいらしい
- 公式ではunity2019.3以降とあるが、clusterのクリエイターキットの対象が2019.4.1LTSになったので、問題なく実行できるようになった。
Compress Assets on Import
- 各ビルド時にいちいちアセットなどを圧縮しないから早くなる雰囲気。
- 投稿日:2020-07-14T16:42:00+09:00
【Unity】gRPC + Protocol BuffersをUnityで実装する
環境
Mac Mojave 10.14.6
Unity 2019.3.9f1
Rider 2019.3.4gRPC is 何?
そもそもgRPCとは「初めまして」の状態だったので、こちらの記事で概要を把握。
環境構築
gRPCのインストール
公式ページからgRPC.ToolsをUnityのプロジェクトに追加する方法もあるようだが、homebrew経由の方が良さそう。
$ brew tap grpc/grpc $ brew install grpcprotobufのインストール
こちらもhomebrewからインストール。
$ brew install protobufプロジェクトにgRPCパッケージを追加
Unityプロジェクトを作成する。
こちらのDaily Builds of master BranchのBuild IDの最新をクリック。
C#の一番上に
grpc_unity_package.v.v.v-dev.zip
があるのでダウンロードする。
zipを解凍すると
Plugins
フォルダが生成されるので、これをプロジェクトのAssets
配下に追加する。protobufのバージョンを下げる
最新(2020/06/05時点)のgRPCパッケージを追加すると、警告+エラーが発生する。
こちらの記事を参考にProtobufのバージョンを3.9.1にする。Download Packageをクリックすると
google.protobuf.3.9.1.nupkg
がダウンロードされるので、.nupkg
を.zip
に変更して解凍する。Assets/Plugins/Google.Protobuflib/net45/
を解凍後のlib/net45/
に置き換える。.protoの作成
公式ページを参考にしてこんな感じの.protoを作成。
gRPCによりHelloService
のサーバー用、クライアント用メソッドがそれぞれ書き出される。hello.protosyntax = "proto3"; message Request{ string name = 1; } message Response{ string hello = 1; } // Requestを引数に渡してSayHelloを呼び出すと、Responseが返ってくる service HelloService { rpc SayHello(Request) returns (Response) {} }.protoをコンパイル
以下のコマンドを実行すると、指定したディレクトリに
Hello.cs
とHelloGrpc.cs
が生成される。$ protoc -I .protoファイルがあるディレクトリ --csharp_out=Hello.csの出力先 --grpc_out=HelloGrpc.csの出力先 --plugin=protoc-gen-grpc=/usr/local/bin/grpc_csharp_plugin .protoファイル名クライアントの実装
クライアント用の
SayHello
メソッドが用意されている。これにリクエストを渡すことで、サーバーからのレスポンスを受け取れるようになっている。
ちなみに非同期メソッドSayHelloAsync
も用意されている。TestClient.csusing Grpc.Core; using UnityEngine; public class TestClient : MonoBehaviour { void Start() { var channel = new Channel("localhost:50051", ChannelCredentials.Insecure); var client = new HelloService.HelloServiceClient(channel); // リクエストを送信してレスポンスをもらう var response = client.SayHello(new Request() { Name = "TOM"}); Debug.Log(response.Hello); } }詳しい事は公式を参照。
サーバーの実装
HelloServiceBaseを継承したクラス
コマンドで生成された
HelloGrpc.cs
にあるHelloServiceBase
クラスを継承したクラスを作成する。このHelloServiceBase
クラスにはvirtualなSayHello
メソッドが用意されているのでオーバーライドして、サーバーとしての処理を実装する。TestServer.csusing System.Threading.Tasks; using UnityEngine; using Grpc.Core; public class TestServer : MonoBehaviour { private void Start() { var server = new Server() { Services = { HelloService.BindService(new TestServerService())}, Ports = { new ServerPort("localhost", 50051, ServerCredentials.Insecure) } }; server.Start(); } } // HelloServiceBaseを継承したクラス public class TestServerService : HelloService.HelloServiceBase { public override Task<Response> SayHello(Request request, ServerCallContext context) { // リクエストを受けて値を返却する var hello = $"Hello {request.Name}"; var response = new Response{Hello = hello}; return Task.FromResult(response); } }詳しくは公式を参照。
試してみる
サーバーサイドのアプリをビルド
TestServer.cs
を適当なゲームオブジェクトにアタッチしたシーンをMacのアプリとしてビルドする。ビルド出来たら起動しておく。クライアントの実行
TestClient.cs
を適当なゲームオブジェクトのアタッチしてUnityEditorを再生する。結果
クライアントから送った値がサーバーで加工されて返ってくることが確認できた。
ハマった点
brew install protobuf
のタイミングによっては、コンパイルされたコードでGOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
という定義が無いためにエラーが発生した。
homebrewでインストールするprotobuf、サイトからダウンロードするgrpc_unity_package.v.v.v-dev.zipのバージョンにズレが生じたっぽい。
今回は下記を参考にして古いバージョンのprotobufをインストールすることで解決した。
Homebrewで過去バージョンのパッケージをインストールする方法参考
https://note.com/npaka/n/n050b1aba7772
https://qiita.com/muroon/items/4e12dde47b9e8b1e94d3
https://qiita.com/nikaera/items/fdcad59bd9a0ebf6a792
https://github.com/grpc/grpc/tree/master/examples/csharp/HelloworldUnity#build
- 投稿日:2020-07-14T14:42:13+09:00
[Unity]Shader書く人は.cgincがあると幸せになれる
前書き
一度ShaderGraphを使用してあまりの便利さにLabで書くのをやめようとしたDemです。
Unityも便利な機能が増えてきていますが、やはり勉強しながらならちゃんと書いた方がいいですね。よく使われるやつ
よくUnlitShaderを書く際に#include"UnityCG.cginc"と書くことがありますね。
これを読み込むとUnity側が用意してくれている便利な機能が一通り使用可能になります。そもそも作成時でデフォルトで書かれていますが。
実際このUnityCG.cgincの中身もGitHubから見ることができたりします。
こちらから飛ぶことができます。
使用していてもまだまだ使ったことない機能がたくさんありますね・・・。.cginc作ってみよう
自作した関数などを.cgincにまとめていつでも使えるようにしてみましょう。
作り方は簡単で...
メモ帳を作って拡張子を.cgincにするだけです。
はい、これだけです。簡単ですね。あとはこの中に自作関数を記述するだけです。
では、サンプルとして僕がテストで割と使用するリムライトを.cginc内に記述してみましょう。Hoge.cginc//RimLightの計算 //1: float UnlitRimLight(float3 normal, float3 worldPos, float rimPower) { //頂点のワールド座標からカメラの位置のベクトルを求める float3 L = normalize(worldPos.xyz - _WorldSpaceCameraPos.xyz); //dotで値が0だと垂直で、1だと平行 1-して値を逆にする float d = 1 - saturate(abs(dot(normal, L))); d = pow(d, rimPower); return d; }読み込み方法は同じで#include".cgincファイル"で読み込みます。
RimLight.shaderShader "Unlit/RimLight" { Properties { _RimPower("Rim Power",Range(0.1,5.0)) = 2 [HDR] _RimColor("Rim Color",Color) = (1,1,1,1) } SubShader { Tags { "RenderType"="Transparent" "Queue" = "Transparent"} Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "../cginc/Hoge.cginc" struct appdata { float4 vertex : POSITION; float3 normal:NORMAL; }; struct v2f { float3 normal:NORMAL; float3 worldPos:TEXCOORD0; float4 vertex : SV_POSITION; }; float _RimPower; float4 _RimColor; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.worldPos = mul(unity_ObjectToWorld, v.vertex); o.normal = UnityObjectToWorldNormal(v.normal); return o; } fixed4 frag (v2f i) : SV_Target { float3 normal = normalize(i.normal); float c = UnlitRimLight(normal,i.worldPos,_RimPower); return _RimColor * c; } ENDCG } } }fragの部分がずいぶんとすっきりしますね。関数名もしっかりと命名すればどんな機能かもわかりやすくなります。
読み込み方が"../cginc/Hoge.cginc"となっているのはファイルパスの問題です。Shaderから見て.cgincファイルがどこにあるのかを
把握して読み込みましょう。
僕はこんな感じでcgincとShaderのファイルを分けているため、上記のような書き方をしています。
終わりに
Shaderを書いて汎用性があるならとりあえずcgincにまとめてみるのもいいでしょう。肥大化してきたら機能ごとに分けたりすると後々使いやすくなったりもしますからね。
ではでは、またどこかで・・・。
- 投稿日:2020-07-14T01:42:20+09:00
Unity 学習 4日目
プログラミングに挑戦1
昨夜、Visual studio が未インストールのため中断したところから再開
Debug.Log("Hello,World");Visual Studioにて、上記を打ち込み、コンソールにリターンがあった!成功
ついに私もプログラマー(´ω`)ちょっとうれしい(笑)
C#言語
{}で囲われたブロックで構成
大枠のブロックをクラスという。1つのスクリプト=1つのクラス
スクリプト名=クラスの名前
これがルールクラスの中に含まれているブロックをメソッドという
レッスン10にてこのメソッドのレクチャーがあるらしいプログラミングに挑戦2
Rigidbody:オブジェクトに力を与えるコンポーネント
オブジェクト、コンポーネント、数値を使うときには変数の箱に入れる必要があるRigidbody rb;これは、宣言:Rigidbody型の変数『rb』を定義しますという意味
rb = GetComponent<Rigidbody>();この式の右側は「rigidbodyを取得して戻り値として帰る」という指示で左のrbに変数に値を代入するという命令となる
void Start()最初に1回だけという意味
void Update()1秒間に数十回のスピードで実行を繰り返すという意味
float moveH = Input.GetAxis("Horizontal"); float moveV = Input.GetAxis("Vertical"); Vector3 move = new Vector3(moveH, 0, moveV); rb.AddForce(move);3次元はVector3の言語を使うことで定義できるのねーおもしろいわ
この式でどうやらボールを前後左右に動かせるらしいできたと思ったらエラー
何が問題かよくわかりません。
次の講座でエラーの原因を教えてくださるそうです。
Rigidbody関係なのかな????うーん。わからん。あとがき
プログラミングの鱗片を体験しましたが、第一印象は難しい。
何が難しいって、スペルミスが多く発生して、講座以外のミス連発からのスペルチェック(時間の無駄)
Visual studioに補完機能があるようなのですが、うまく動いていない印象
先人たちの努力に敬意を表します。今日もありがとうございました。