箱庭の音
音を基軸としたコンテンツを作ってみたかった
たまにMVとかを自動化できたら面白そうかなとか思っていたので形にするならどうなるんだろう?と思って作りました
音によって色々なパラメーターが変わるコンテンツです
※音が出ます
音に合わせてカメラが揺れたり、傘の移動速度が変わったりします。
さらに音を好きな音楽に変えることができてwavファイルのドラッグ&ドロップで放り込めば切り替わって、切り替えた音を取得して動きが変わるコンテンツになります
音によって空間の動きが変わるけど一部しか観れないので箱庭っぽいなぁということで「箱庭の音」というタイトルにしています(多少キャッチーなタイトルがよかったかも)
影しか写らない横断歩道は自分の世界観なだけなので特に理由がないです
開発環境など
コアとなる部分はUnityで作っていてドラッグ処理などをVue.jsで繋げています
有料Assetsも使ってるのでリポジトリを公開しているもののUnityプロジェクトは誰でも触れるものにはなってないです。。。
Vue.jsから11MBのファイルをUnityに渡すためにbase64するとメモリが足りなくなったりと意外と気を遣うところが出てきたりしました。。。
あとはVue.jsをまともに触るのは初めてだったので作りがかなりイケてないんだろうなと思ってますが作りきることのが大事だと思ってるのでとりあえず作りました(cssが相対的でなかったりビルド後のファイルパスを相対的に治したり…設定があるんだろうけど動かしたかった)
wavファイルを動的ロードする際にUnityWavというのを使ったのですがバイナリの読み取りに柔軟性がなくforkして修正するなどしてました → forkしたリポジトリ
そしてAudioの数値取得は
AudioSource-GetSpectrumData - Unity スクリプトリファレンス
で通常はできるのですがWebGLだと動かないため
を使って実装しました、、、動いてよかった
ホントはSoundCloudのapiを叩いて自由度もあげたかったけどノウハウなさすぎたので一旦断念中
実は昔のプロジェクトをベースとしている
UnityをVueで動かすノウハウ Unityで吐いたWebGLをPWAで動かしてみた - Qiita
遊んでただけの音からパラメーター取るロジックや
ちゃんと修復するところから速攻壊れるところまで撮影できた#unity3d #madewithunity pic.twitter.com/UzDvtk4DiF
— あるど (@OrangeGKeeper) April 4, 2018
見た目に凝ろうとして途中断念したプロジェクトを掛け合わせて作りました
バグで荒ぶる豆腐と影だけの傘 pic.twitter.com/01QjYmWsIM
— あるど (@OrangeGKeeper) March 12, 2019
そのため二週間くらいで作りきれたので蓄積大事だなと思っています
さいごに
今後「箱庭」の種類を増やして音を分析して自動的に見た目を変えたりしていきたいと思っています
そのために
を使ってもっと取得できるパラメーターを増やして遊べるとよさそうだなぁと思ったり
動画とはちょっと違うところがありますが動画としてみれるようにpinp(ピクチャーインピクチャ)機能を使う表示も視野にいれてみたい…
Unity2019.3からのXcodeプロジェクトでSwiftが使えるのか検証
obj-cを書きたくない
シンプルにそれだけ
僕はSwiftが使いたい
そして来たるUnity2019.3…Unityのコア部分が.frameworkになるらしい
まぁそれだけなら気にしないしBuildのPostProcessを変えるくらいだろうと思ったら
下のコメントに
However for iOS, we won’t be supporting SWIFT for now, our focus in on Objective C.
Swiftのサポートは考えてない…?
え、まじで
まずは動かす環境を整える
2019.3.5f1を検証に選びリポジトリは以前
Unityのネイティブプラグイン(macOS/iOS/tvOS)のソースコードを共通化する - 勉強不足で至らんブログ
で使用した
GitHub - MizoTake/ApplePlatformNativePluginSample
を使うことに
検証のためにリポジトリにあるPostProcessは全部コメントアウトした
動かそう
UnityビルドしてXcodeでビルドするが案の定エラー
エラーが出てきて解決していくが
"Umbrella header not found"
というのだけ解決ができなくて悩んだ
ただネイティブの記事で
というのがありネイティブで可能ならUnityもできるはずと思い調べる
https://forum.unity.com/threads/build-ios-umbrella-error.838879/
Which states that it is a regression bug and is not happening in 2020.1 beta.
まじかよ
ということで2020.1をインストール
動くやんけ
しかもSwiftのバージョン勝手に設定してくれる様になってるやんけ
最高かよ
まとめ
2020ベータなら動いたので2019.3でSwiftのネイティブプラグインを使うのは避けた方が良さそう
これからもSwiftネイティブプラグインは使用可能!
ScreenBrightnessRangeSettingを公開しました
Androidネイティブを作ってみたかった
興味本位と勢いで作ってリリースしました
とてもとても業務レベルには至らないと自分で思いつつ開発していました
スマホの画面輝度の自動調整を範囲制限できるものになります
iOSでできなさそうなものを考えて作ってみました
ソースコード自体は全部公開してますが設計思想も何もないです
初めてのAndroidネイティブアプリでKotlin要素のみという経験でした
バックグラウンドで動かすあたりがとても怪しく勢いです
一番知見だったのは、Google Playストアでもきちんと審査されるようになっているんだな…と…昔は数時間でリリースできたのに今回は4日前後かかった気がします
今後は暇作ってUIとかアプリ名とかぼちぼち更新していこうかなと…
StateMachineBehaviourにInjectする
StateMachineBehaviourにInjectする方法
ZenjectでStateMachineBehaviourを使ってみたいと思ったのが発端で
Zenject/ReleaseNotes.md at master · modesttree/Zenject https://t.co/XoVFTuFTgZ
— あるど (@OrangeGKeeper) 2020年3月4日
> Fixed to automatically inject StateMachineBehaviour derived classes attached to Animator components
😎
検索すると自動的にInjectできるようになったそう…だがMonoBehaviourと同じように[Inject]を付けても実行されない…
調べると
Zenject/ZenjectStateMachineBehaviourAutoInjecter.cs at master · modesttree/Zenject https://t.co/WitRiVG6iV
— あるど (@OrangeGKeeper) 2020年3月5日
naruhodo
ZenjectStateMachineBehaviourAutoInjecter
というのがある
中身をみるとシンプルで
using ModestTree; using UnityEngine; namespace Zenject { public class ZenjectStateMachineBehaviourAutoInjecter : MonoBehaviour { DiContainer _container; Animator _animator; [Inject] public void Construct(DiContainer container) { _container = container; _animator = GetComponent<Animator>(); Assert.IsNotNull(_animator); } // The unity docs (https://unity3d.com/learn/tutorials/modules/beginner/5-pre-order-beta/state-machine-behaviours) // mention that StateMachineBehaviour's should only be retrieved in the Start method // which is why we do it here public void Start() { // Animator can be null when users create GameObjects directly so in that case // Just don't bother attempting to inject the behaviour classes if (_animator != null) { var behaviours = _animator.GetBehaviours<StateMachineBehaviour>(); if (behaviours != null) { foreach (var behaviour in behaviours) { _container.Inject(behaviour); } } } } } }
となっており手動でComponent追加すればStateMachineBehaviourにInjectする感じぽい
ただ前提として 最初からSceneにあること
なので動的にやるとき用に少しだけ変えて
using UnityEngine; using Zenject; namespace Hoge.Components { public class StateMachineBehaviourInjector : MonoBehaviour { public void InjectionTo(Animator animator) { var behaviours = animator.GetBehaviours<UnityEngine.StateMachineBehaviour>(); if (behaviours == null) return; foreach (var behaviour in behaviours) { // DiContainerがProjectContextでいい場合 ProjectContext.Instance.Container.Inject(behaviour); } } } }
って感じで外から呼べるようにして使うようにした
ちゃんとInjectされたのでめでたしメモ
UnityのEditModeTestsをdotnetで実行させる
UnityのTestをUnityEditorを使わないでどうにか走らせれないか?
と考えのがきっかけです。
UnityのCIをCircleCIで頑張る - 勉強不足で至らんブログ
過去CircleCIでUnityEngineが入ったDockerを使っていたりしましたがDockerコンテナのセットアップで
長くて3分弱かかります早くて1分程度にはなります。 docker_layer_caching
を使えば10秒くらいのにもできますがUnityEngineの入ったDockerを使おうとすると工夫が必要になります。
工夫なく手軽に使えたらいいのに…と思ったところで
にある
- 第5章:Unityと.NET Coreでのコード共有
を思い出しました。これでdotnetのtestから走らせればいいのでは…と思ってやってみました。
結果的に今回はEdit Mode Testsであれば可能でした。最後の方に記述しますがPlay Modeももしかするとできるかもしれません。
今回のリポジトリ github.com
CircleCIの結果 https://circleci.com/gh/MizoTake/UnityTestFromDotnet
セットアップ
基本的なセットアップ手順は 第5章:Unityと.NET Coreでのコード共有
にありますのでそちらの手順に添えば大丈夫です。
サンプルリポジトリも公開してるそうです。
github.com
自分は追加でdotnet
のプロジェクトの.csprojに
<ItemGroup> <PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="Unity3D.UnityEngine" Version="2018.3.5.1" /> <PackageReference Include="coverlet.collector" Version="1.0.1" /> <PackageReference Include="NUnit3TestAdapter" Version="3.16.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> </ItemGroup>
を追加しています。基本的にNuGetで検索すればでるはずなので導入方法はやりやすいものがいいと思います。
注意なのは Unity3D.UnityEngine
のバージョンが2018台のいくつかしかないことです。バージョンを超える何かを行たい場合は工夫が必要になると思います。
Testを実行する
普通にC#でEdit Mode Testsを記述します。今回はサンプルで
using NUnit.Framework; public class TestSample { [Test] public void Passed() { Assert.AreEqual(true, true); } [Test] public void Failed() { Assert.AreEqual(true, false); } }
としました。これをUnityのTestRunnerが認識するように作ります。
ただ、少し踏み入ってUnityEngineの参照を行おうとすると参照できないことがあるのでdllの解決をうまくやる必要がありそうです。自分も確認不足でしたのでわかり次第更新します。
あとはdotnet test
を実行すればtestが走り、結果が得れます。
手元で得るよりはCIで走らせて見れた方がいいと思うのでCircleCIで走らせました。
version: 2.1 executors: dotnet: docker: - image: mcr.microsoft.com/dotnet/core/sdk:3.0 jobs: test: executor: dotnet steps: - checkout - run: dotnet tool install trx2junit - run: "dotnet test --logger trx || : ; dotnet trx2junit dotnetProject/TestResults/*.trx --output results" - store_test_results: path: results workflows: version: 2 test-flow: jobs: - test
途中でdotnet toolで trx2junit
というのを導入していますが dotnet test だとtestの結果は.trxという形式で吐き出されるためです。CircleCIではJUnit
とCucumber
しか対応していないので変換させるためにtrx2junit
を使用します。
一度手元でdotnet tool install trx2junit
を実行すれば.configというディレクトリに
{ "version": 1, "isRoot": true, "tools": { "trx2junit": { "version": "1.3.0", "commands": [ "trx2junit" ] } } }
が作成されます。これがあればinstallできるぽいです。もしかすると.configはignoreしていいディレクトリかもしれません。
ともかくこれでCircleCIのTest Summary
に登録でき、エラーがあった場合に
という風に見れるので対処もやりやすくなると思います。
またdotnet test実行時のコマンドは、この形式でないとテストがこけた際にtrxから変換ができずにTest Summaryが使えず終わってしまうのを回避するためのものです。
さいごに
ここまででUnityのEdit Mode Testsをdotnetで実行させる方法の説明は終わりです。UnityEngineがなくても実行できる環境というのは結構魅力的だと思っています。さらにはUnityのactivateが必要ないのでかなり良いです。
いずれPlay Mode Testsも実行させれるようにしてみたいため調べてみると www.nuget.org
があったので試しましたがそのままでは動きませんでした。ただ工夫をすればいけるような感じだったので時間のある時に挑戦してみようかと思います。
Unityでタイムラプスぽいことできないか試した
Unityでタイムラプスの表現できたら面白いのでは?
とアニメのOPなどをみて思いました。タイムラプスって面白いのでどうやったらそれっぽっく表現できるのか試しました。
Time.timeScaleを弄ってるだけでタイムラプスぽくなるの楽しい pic.twitter.com/Vo0537B4fU
— あるど (@OrangeGKeeper) 2020年2月2日
Unityで表現するには簡単で Time.timeScale を弄って大きいする数字にだけでタイムラプスぽく見えるようになりました。
Time.timeScaleを大きくして早送りしてからキャラクターを表示非表示を一定の間隔で行えばいけるかな?と思ったらtimeScaleを弄るだけでおわりました…
一定の値を超えたあたりからそう見えるので閾値がありそうだなとは思いました…ができたことに満足したので終わりました。。。
Unityのネイティブプラグイン(macOS/iOS/tvOS)のソースコードを共通化する
ネイティブプラグインの動作確認
iOS/tvOSのネイティブプラグインはEditorでは動かせません。そこでmacOSで同じソースコードを動かせばいいのでは?と考えて動かしてみました。
ただ全てが動くわけではないと思いますし一部機能の制限が入ります。調べ尽くしてないので、もしかすると使えます。わかっているのは以下の一点です。
- entitlementファイルを使う場合は.bundleにcodesignができれば動きそう(パッと試した感じはできなかった)
一点といいつつ結構範囲が大きいです。あくまでEditorで動かす.bundleにする際にできないというだけで.appにcodesignを使えば動くはずです。
リポジトリはこちら
Editor(macOS)での動作はもちろん、シミュレーターになりますがiOS/tvOSで動作確認をしました。
Editor(macOS) | iOS | tvOS |
---|---|---|
実装
今回Swiftにてコアのコードを記述しました。
import Foundation @objcMembers public class Sample : NSObject { public override init() { super.init() } public func Call() -> String { "From Swift Code" } }
Objective-CでラップしてC#側でStringをTextMeshProForUGIに表示させています。
Editorで動かすためのXcodeProjectを作る
UnityのPluginsディレクトリに.swiftや.mmがある前提で話をします。
まずはXcodeでProjectの新規作成を行ます。
UnityEditorでは.bundleというフォーマットで動作をするのでBundleのテンプレートを選択します。
次にプロジェクト名を求められるのでお好きなプロジェクト名を入力します。
これで保存場所を選択して作成完了です。
これからUnityのPlugins配下にあるファイルを参照してXcodeのプロジェクトに含めます。 ファイルを選ぶ際にコピーするかどうかのオプションがりますが別ファイルになってしまうのでOFFにしておいた方が良いです。
info.plistの入っているディレクトリを右クリックして以下の項目を選択します。
次にSwiftを使用する設定です。 先ほどのファイル追加で処理が走り、Swiftなどの設定が増えます。そこで
左の青いアイコンを選択して Build Settings
を選びます。そこから Basic
Customized
All
と選ぶポイントがあるので All
にして検索ボックスに -swift.h
と検索します。
そして Objective-C Generated Interface Header Name
のところをUnityのPlayerSettingsで設定するProduct Nameを確認して {ProductName}-Swift.h
と入力しておきます。
こうすることでUnityでiOS/tvOSのプロジェクトが吐かれた時にエラーが出なくなります。
これで準備ができたのでXcodeのRunボタンでDebugモードでビルドします。
ビルドすると Products
ディレクトリ配下にbundleができるのでUnityのPluginsディレクトリ配下におきます。
Show in Finder
を選択するとFinderでドラッグ&ドロップできるのでおすすめです。(xcodeのpostprocessに移動するscriptを書けばいいのですがめんどくさかった…)
Editorで動かす準備ができました。
C#でプラグインを呼ぶ
C#で呼ぶ処理を書いて動かしてみましょう。
今回はC#でこう書きました。
using System.Runtime.InteropServices; using TMPro; using UnityEngine; namespace ApplePlatformNativePlugin { public class SampleText : MonoBehaviour { [SerializeField] private TextMeshProUGUI centerText; #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX private const string LibraryName = "XcodeProject"; #elif (UNITY_IOS || UNITY_TVOS) && !UNITY_EDITOR private const string LibraryName = "__Internal"; #endif [DllImport (LibraryName)] private static extern string CallNativeString(); void Start() { centerText.text = CallNativeString(); } } }
これでSceneに配置してUIに表示させています。
おわりに
以上がAppleのプラットフォームのネイティブプラグインを共通化させEditorで確認する方法でした。これであれば実機でしか動かせない!という時も処理だけならEditorで簡易に確認が可能かと思います。 資格情報の署名がわからず、このままでは機能が一部動作しませんが一旦はいいかなと思っています。