- 投稿日:2020-09-22T15:18:01+09:00
Unity ML-agents で実行条件を変えて学習時間を比較してみた
CPU/GPU、UnityEditor/ビルド、ビルドの複数実行、Agentの複数実行と、
実行条件を変えて学習時間を比較してみました。
プログラムはRollerBallを参考につくっていて、こちらに挙げてあります。環境
- Windows10
- Python 3.7.9
- TensorFlow 2.3.0
- Unity 2019.4.10f1
- ML-Agent Release6
学習の高速化
- GPU で計算する(判断基準は下に記載)
- ビルドした exe で学習させる
- --env
- --no-graphics オプション : 画面表示なし
- 複数同時起動、CPUのマルチコア(スレッド)が最大
- --num-envs
- Agent を複製して実行する
Behavior ParameterのInterface DeviceにGPUを設定する判断基準
単純な推論であればCPUのほうが早い。GPUを選択する基準は以下の通り。
1. Visual Observation
2. エージェント数 * Observation > 1024
3. エージェント数 * 隠れ層の数 > 1024学習時間の計測結果
手法 学習時間(秒) CPU使用率 補足 UnityEditor 68 25 CPU GPU 71 25 Behavior Parameter に GPU を設定、※1 ビルド 86 13 ※2 複数同時起動 55 35 --num-envs=4 Agent 複製 21 25 複製4つ、UnityEditor ※1 それぞれ1回の測定なので、数秒は誤差の範囲
※2 ビルド版が UnityEditor より遅くなっているのは、Python とビルドアプリがCPUを食い合っているためだと思われる
- 投稿日:2020-09-22T12:42:21+09:00
Could not establish connection with unity package manager
open terminal type in
setx UNITY_NOPROXY localhost
- 投稿日:2020-09-22T12:39:49+09:00
5 Czekotolada による 質問 · 2019年02月25日 17:18 · c#package Could not establish connection with unity package manager
open terminal
setx UNITY_NOPROXY localhost
- 投稿日:2020-09-22T09:26:35+09:00
【webGL】ブラウザだとカクついて動かなかったお話【chrome】
この記事でできること
- unityroomで作品を公開した際、もしカクついて全く動かないなぁ、というときに、chromeの設定で解決できるかもしれない。
- キーワード…「ハードウェア アクセラレーション」
経緯と問題
FieldWalkingをunity1weekGAMEJAMで公開後、評価期間が終了したのでアップデートを繰り返していました。
その途中、演出としてボリュームを上げたところ、ブラウザ上ではかくついて確認できなくなりました。
あれこれと
Unityの描画クオリティであったり、
カメラのカリング設定もしましたが、
ブラウザ上では動作確認が難しい状態が続きました。chromeの設定を見てみると、
「ハードウェア アクセラレーションが使用可能な場合は使用する」の項があったので
google先生に確認したところ、推奨としてはオンのようでした。(調査時点ではオフでした)
結果
chromeの「ハードウェア アクセラレーションが使用可能な場合は使用する」をオンをしたら、
ブラウザ上でも確認することができました。
宣伝
unityroomの1weekGAMEJAMで公開した2作品は、評価期間終了後もアップデートしています。
ぜひプレイしていってください。
- FieldWalking (https://unityroom.com/games/fieldwalking)
- AddBalance (https://unityroom.com/games/addbalance)
また、AddBalanceについては、cluster版も試作としてリリースしました。
こちらもみなさまアバターで遊びに来てくださいませ!!
- AddBalance for cluster (https://cluster.mu/w/ef49e840-f2a4-4eca-817d-9ef4b54060a1)
- 投稿日:2020-09-22T08:45:43+09:00
【webGL】Uncaught RangeError: Maximum cal stack size exceeded【このエラーなに?】
- 投稿日:2020-09-22T04:03:09+09:00
MagicLeapで床にオブジェクトを配置する方法
開発環境
Unity : 2019.3.7f1
LuminOS : 0.98.11, APILevel 8
MagicLeap : UnitySDK 0.24.1
MagicLeap : ToolKit 特にバージョン表記等はないので現時点(2020/09/22)での最新今回開発したアプリのリポジトリはこちらになります
完成するもの
床を判定するやつ pic.twitter.com/zzhb4lk5g2
— 松本隆介 (@matsumotokaka11) September 21, 2020下準備
ProjectSettings > MagicLeap > ManifestSettings
にて以下の項目にチェックを入れました
- ControllerPose
- LowLatencyLightwear
- WorldReconstruction
スクリプト等
今回のスクリプトはMagicLeap ToolKitのPlaceOnFloorを改造したものです
素のPlaceOnFloorのままだと初回の床判定以降は床判定を行わないので何度でも床判定を行えるようにしました。
改造したFloorChecker.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; #if PLATFORM_LUMIN using UnityEngine.XR.MagicLeap; #endif namespace FloorCheck { /// <summary> /// MagicLeapToolsのFloorOnPlaceを改造したクラス. /// 床検知を何度もにできるようにする. /// </summary> public class FloorChecker : MonoBehaviour { readonly float HeadLocationIdleThreshold = 0.003f; readonly float HeadRotationIdleThreshold = .3f; readonly int HistoryCount = 5; readonly float HeadIdleRequiredDuration = .2f; // Public Properties: public Vector3 Location { get; private set; } [Tooltip("Does content's content match it's transform forward?")] [SerializeField] bool flippedForward; List<Vector3> headLocationHistory; List<Quaternion> headRotationHistory; float headLocationVelocity; float headRotationVelocity; Transform mainCamera; bool headLocationIdle; bool headRotationIdle; bool headTemporarilyIdle; bool headIdle; bool placementValid; //Init: void Awake() { //refs: mainCamera = Camera.main.transform; //requirements: if (FindObjectOfType<MLSpatialMapper>() == null) { Debug.LogError("PlaceOnFloor requires and instance of the MLSpatialMapper in your scene."); } } //Flow: void OnEnable() { //sets: headLocationHistory = new List<Vector3>(); headRotationHistory = new List<Quaternion>(); } //Loops: void Update() { //let headpose warmup a little: if (Time.frameCount < 3) { return; } HeadActivityDetermination(); } //Coroutines: IEnumerator HeadIdleTimeout() { yield return new WaitForSeconds(HeadIdleRequiredDuration); headIdle = true; } void HeadActivityDetermination() { //history: headLocationHistory.Add(mainCamera.position); if (HistoryCount < headLocationHistory.Count) headLocationHistory.RemoveAt(0); headRotationHistory.Add(mainCamera.rotation); if (HistoryCount < headRotationHistory.Count) headRotationHistory.RemoveAt(0); //location velocity: if (headLocationHistory.Count == HistoryCount) { headLocationVelocity = 0; for (int i = 1; i < headLocationHistory.Count; i++) { headLocationVelocity += Vector3.Distance(headLocationHistory[i], headLocationHistory[i - 1]); } headLocationVelocity /= headLocationHistory.Count; //idle detection: if (headLocationVelocity <= HeadLocationIdleThreshold) { if (!headLocationIdle) { headLocationIdle = true; } } else { if (headLocationIdle) { headLocationIdle = false; } } } //rotation velocity: if (headRotationHistory.Count == HistoryCount) { headRotationVelocity = 0; for (int i = 1; i < headRotationHistory.Count; i++) { headRotationVelocity += Quaternion.Angle(headRotationHistory[i], headRotationHistory[i - 1]); } headRotationVelocity /= headRotationHistory.Count; //idle detection: if (headRotationVelocity <= HeadRotationIdleThreshold) { if (!headRotationIdle) { headRotationIdle = true; } } else { if (headRotationIdle) { headRotationIdle = false; } } } //absolute idle head determination: if (headLocationIdle && headRotationIdle) { if (!headTemporarilyIdle) { headTemporarilyIdle = true; StartCoroutine(HeadIdleTimeout()); } } else { if (headTemporarilyIdle) { headIdle = false; headTemporarilyIdle = false; StopCoroutine(HeadIdleTimeout()); } } } /// <summary> /// 指定したRayの位置に床があるか否か、ある場合はその座標も返す. /// </summary> /// <param name="ray"></param> /// <returns></returns> public (bool, Vector3) LookingAtFloorDetermination( Ray ray) { //cast to see if we are looking at the floor: RaycastHit hit; if (Physics.Raycast(ray, out hit)) { MagicLeapTools.SurfaceType surface = MagicLeapTools.SurfaceDetails.Analyze(hit); if (surface == MagicLeapTools.SurfaceType.Floor) { Location = hit.point; placementValid = true; return (true, Location); } else { placementValid = false; return (false, Vector3.zero); } } else { placementValid = false; return (false, Vector3.zero); } } } }FloorCheckerを利用するFloorCheckOnPlaceContent.cs
using System; using MagicLeapTools; using UnityEngine; namespace FloorCheck { /// <summary> /// トリガを入力したときに床を判定し、床の場合はオブジェクトを配置するサンプル. /// </summary> [RequireComponent(typeof(FloorChecker),typeof(AudioSource))] public class FloorCheckOnPlaceContent : MonoBehaviour { [SerializeField] AudioClip pressClip; [SerializeField] AudioClip successClip; [SerializeField] AudioClip failedClip; [SerializeField] GameObject content; [SerializeField] Pointer pointer; FloorChecker floorChecker; AudioSource audio; void Start() { floorChecker = GetComponent<FloorChecker>(); audio = GetComponent<AudioSource>(); } public void OnTriggerDown() { audio.PlayOneShot(pressClip); (bool onFloor, Vector3 pos ) result = floorChecker.LookingAtFloorDetermination(new Ray(pointer.Origin, pointer.Direction)); if (result.onFloor) { audio.PlayOneShot(successClip); content.transform.position = result.pos; } else { audio.PlayOneShot(failedClip); } } } }シーンの構成
シーンの構成は以下の画像の通りになっています
MainCameraは
Assets > MagicLeap > Core > Assets > Prefabs
にある物を使いました
ControlPointerは
Assets > MagicLeap-Tools > Prefabs > Input
から
今回はSpatialMapperを表示してどのメッシュの判定が通っているかをわかりやすくするので
Assets > MagicLeap > Core > Assets > Prefabs
のMLSpatialMapperも利用しますMLSpatialMapperにはメッシュを生成するルートとなるオブジェクトが必要なのでシーン上にMeshRootオブジェクトを作成しそれをあてがっています
FloorCheckerを利用するクラス等はこのような構成になります
効果音は魔王魂さんから拝借トリガ入力に対応して床判定を行うためにControlPointerのイベントにFloorCheckOnPlaceContentのOnTriggerDownを登録しています
完成
実機にビルド or ZeroIterationで動作確認をすれば
床を判定するやつ pic.twitter.com/zzhb4lk5g2
— 松本隆介 (@matsumotokaka11) September 21, 2020これで床を判定し、床だけに配置したいオブジェクトとかの実装ができるようになります
感想
この判定を使えば床判定の入ってるメッシュだけAgentのNavMeshを晴れたりできるかも?
まだやってない、出来たら記事にするかもしれません
- 投稿日:2020-09-22T00:16:53+09:00
UVScrollシェーダーの書き方
はじめに
この記事は以下のサイトの記事を参考にさせていただいてます
https://qiita.com/Nekomasu/items/d50a4409e48ad77bc7f2
https://amagamina.jp/unity-shader/制作背景的な
そもそもUVスクロールをなぜ作ろうとしたの?
->インターンの実装で少しでも画面をにぎやかしたかったから。
以上!!!仕様的なもの
UnlitShaderで作成
必要プロパティ
+ テクスチャを入れるためのMainTex
+ X軸のスクロールスピードを制御する_ScrollX
+ Y軸のスクロールスピードを制御するScrollY時間が進むごとにスクロールさせたいので定義済みの値である_Timeをスクロールの処理に追加
実際のコード
UVScroll.shaderShader "Unlit/UVScroll" { Properties { _MainTex ("Texture", 2D) = "white" {} _ScrollX("X ScrollSpeed",Range(0.0,1.0))=0.1 _ScrollY("Y ScrollSpeed",Range(0.0,1.0))=0.2 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float _ScrollX; float _ScrollY; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { i.uv.x += _ScrollX * _Time; i.uv.y += _ScrollY * _Time; // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
- 投稿日:2020-09-22T00:14:33+09:00
UnityPlugin/Android/基本
[環境]
OS: windows10 pro
IDE:Android Studio4.0.1
Unity 2019.4.5f1
確認した実機: Galaxys8[参考]
[Android用Plugin(java[aar])の作成(https://qiita.com/fukaken5050/items/c9ac144344c5f6ff9f57)
https://dream-target.jp/2019/01/04/unity_android/
https://qiita.com/okuhiiro/items/1aaec487d1ab8b086095
https://ghoul-life.hatenablog.com/entry/2019/01/26/030622
https://note.com/attomicgm/n/ncb22f460e8b6https://baba-s.hatenablog.com/entry/2018/09/18/170000 確認済
本文
UnityでAndroidProjectを出力する
・適当にCUBE等を配置する。
・Unityでプロジェクトを作成する(例:TestAndroidPlugin)
・「ExportProject」「DevelopmentBuild」にチェックします。
・AndroidにスイッチしバンドルIDを設定する。
・com.ore.TestAndroidPlugin) → Javaでは重要なので意識してください。com.ore.TestAndroidPluginとなってる華胥ありますが私はここでつまづきました
・MinimumAPILevelを設定する(例:Android4.4 APILevel19) デフォルト
・Unityプロジェクトと同じフォルダにExport用フォルダを作成し、フォルダに移動してから「フォルダの選択」を押す(例:TestAndroidPlugin\Android)
・AndroidStudio用プロジェクトが生成されるAndroidStudioで読み込む
UnitySDKかAndroidStudioのSDKを使うか指定する。
プロジェクト解析にすこし時間がかかります。
・ビルドエラーは出ず問題なく実行できます。Unityの機能をAndroidから使うため、classes.jar/android.jarを配置します。
今回の環境では以下に存在しました。
C:\Program Files\Unity\Hub\Editor\2019.4.5f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\ClassesC:\Users\user\AppData\Local\Android\Sdk\platforms\android-30\
C:\Android\SDK\platforms\android-30プラグインモジュールの追加
・メニューの「File」>「New」>「NewModule」を押す
・「AndroidLibrary」を選択し、「Next」を押す
・「Application/Library name」を設定する(例:UnityPlugin)
・「Package name」を右側の「edit」を押し、設定し、「done」を押す(例:com.ore.unityplugin)
・「MinimumSDK」をUnityに設定したものと同じか、小さいものに設定する(例:API23)
・「Finish」を押す
■「build.gradle」の編集
Unityライブラリファイル"unity-classes.jar"(またはclasses.jar)を、出力されるaarファイルに含めないようにします。
//classes.jarファイルは、コンパイルのときのみ使用する //Android Studio 3系では、「implementation fileTree」と記述すると //classes.jarも含まれてしまうため「compileOnly」と記載して //jarファイルはコンパイルのみ使用するようにします。 dependencies { //implementation fileTree(dir: "libs", include: ["*.jar"]) NG compileOnly fileTree(dir: 'libs', include: 'unity-classes.jar') implementation 'androidx.appcompat:appcompat:1.2.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' }・右上に出ている「SyncNow」を押す
プラグイン用javaクラスの追加
・プロジェクトツリーから「プラグイン名」>「Java」>「パッケージ名」を選択(例:unityplugin>Java>com.ore.unityplugin)
・(AndroidTest)や(Test)と書かれていないもの(一番上)
・メニューの「File」>「New」>「JavaClass」を押す
・「Name」を設定(例:TestPlugin)
・「OK」を押す
・以下はトースト表示する簡単なサンプルpackage com.ore.unityplugin; import android.app.Activity; import android.widget.Toast; import com.unity3d.player.UnityPlayer; public class TestPlugin { public static void showToast(final String message) { final Activity activity = UnityPlayer.currentActivity; activity.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(activity, message, Toast.LENGTH_SHORT).show(); } }); } }UnityPlayerでビルドエラーがでるので、unityLibrary-libsの[unity-classes.jar]を UnityPlugin-libsにコピーする。IDE右上の[SyncProject with Gradle]を押すとビルド成功します。
・aarのサイズは16K程度です。100kくらいある場合はunity-classes.jarも含んでおり、プラグイン利用時にUnityが持つJarと衝突します。作成したPluginを使う
UnityProject/Asset/Plugins/Androidに作成したプラグイン *.aar を配置する。
スクリプト
TestPlugin を作成して適当なGameObjectに配置する。UnityでButtonとTextを生成してTestPlugin と接続する。
最後にAndroid実機で動作確認をする。using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class TestPlugin : MonoBehaviour { [SerializeField] private Button _button = null; public Text m_text = null; private void Start() { _button.onClick.AddListener(() => OnButtonClick(_button)); m_text.text = "start"; } private void OnButtonClick(Button button) { m_text.text = "OnButtonClick_1"; using (AndroidJavaClass javaClass = new AndroidJavaClass("com.ore.unityplugin.TestPlugin")) { Debug.Log("OnButtonClick"); m_text.text = "OnButtonClick_2"; javaClass.CallStatic("showToast", "Test"); } } }
- 投稿日:2020-09-22T00:00:52+09:00
UnityでHTTP(GET)通信によるJSONデータ取得
たまに使うことあって、
その都度「どうだったけー?」って悩むので自分用備忘録。UNityアセットストアから
JSON Object
というアセット をダウンロードプログラム中、GET通信したいタイミングに
StartCoroutine(connect("https://URL"));を記述。
こんな感じupdate.csvoid Update() { //通信したいURLを代入 StartCoroutine(connect("https://URL")); } IEnumerator connect(string url){ WWW www = new WWW(url); yield return www; print(www.text); JSONObject json = new JSONObject(www.text); //powerというkeyのvalueを取得 JSONObject power = json.GetField("power"); print("power is " + power.n); ; }