Unityがプロジェクト選択画面で固まる謎の不具合の回避方法
昨日からプロジェクト選択画面で特定のプロジェクトだけ起動しなくなると言う謎の不具合が発生しました。
自分の知り合いも何人か同じ状況になっているらしくフォーラムでも同様の問題が発生してる人がたくさんいるようでした。
Error | Unity Community
自分は5.5、5.6で発生することを確認し、知り合いは2017で発生したそうです。
Mac、Windows共に発生することを確認しました。
Workaround
色々試してみてWorkaroundを見つけたので紹介したいと思います。
- PCのネットワークを切断して起動
シーンを直接起動- /etc/hostsに「127.0.0.1 update.unity3d.com」を追加
このどれかの方法で無事起動させることができます。
原因
原因はいったいなんなのかUnity Editorのログをみてみます。
Downloading http://update.unity3d.com/5.6/ivy.xml to /var/folders/lc/7qgqzqvj4bs6shhq1rj88mm00000gp/T/unity/49bf52e2-32e5-4419-91db-05383a6d686d/ivy.xml
Registered platform support modules in: 0.180029s.
Native extension for OSXStandalone target not found
Native extension for WebGL target not found
Loading native library: UnityEditor.iOS.Native at /Applications/Unity/PlaybackEngines/AppleTVSupport/UnityEditor.iOS.Native.dylib
[usbmuxd] Start listen thread
[usbmuxd] Listen thread started
[usbmuxd] Send listen message
Native extension for tvOS target not found
Native extension for iOS target not found
Native extension for Android target not found
Begin MonoManager ReloadAssembly
Shutting down Remote Indexer
Task failed: Downloader Task
Cancelling tasks, domain is going down
ログはここで止まっています。
Unity Edtiorの動きをみるとずっとローディングを続けていて無限ループに陥ってるような挙動をします。
ログに書かれている「http://update.unity3d.com/5.6/ivy.xml」にアクセスすると404になっているのでUnityのサーバの問題でしょうか?
詳細な原因はソースを見れない為わからないのですが、おそらくivy.xmlが404で取得できない時、特定の条件が重なると(自分の環境ではScriptが大量にあるプロジェクトで起きやすかったです)発生するように思えます。
なのでivy.xmlを参照しているプロジェクト選択画面を回避して直接シーンファイルを開いたり、ネットワークを切断したりする方法が有効なようです。
実はこれをみると結構昔のバージョンから発生している問題のようで、Unityのサーバに問題が起きた際に浮き彫りになってきたのでしょうか?
Error | Unity Community
おそらくサーバが復旧したら普通に起動できるようになるのかとは思うのですが、根本的なUnity Edtiorのエラー処理を修正して欲しいところであります。
現在は復旧して公式でアナウンスがされたみたいです。
Unity Editor がハングアップする問題 – ユニティ・テクノロジーズ・ジャパン合同会社
iOS11のARKitをUnityから使用してみる
iOS11が発表されiOSにARKitという新しいARサポートが入りました。
こちらはUnityやUnreal EngineからPluginを通して使用する事できるそうなのでUnityを使ってオブジェクトを表示してみました。
必要なもの
- iOS11にUpdateしたiPhone 6s以上の端末(ARは実機じゃないと確認できません)
- XCode 9(現在β)
- Unity 5.6.1p1以上
- Unity ARKit Plugin
STEP
#1. Unity ARKit Pluginをプロジェクトにインポート
#2. Player SettingsのCamera Usage Descriptionを設定(これを設定しないとアプリがクラッシュします。)
#3. Main CameraにUnityARVideoコンポーネントを追加し、UnityARVideoのClear MaterialにYUVMaterialを設定
#4. UnityARGeneratePlane Componentをシーンのオブジェクトに追加(これを追加すると平面を検知してくれるようになります。)
これで準備は整いました。
あとは下記のようなソースを追加してみます。
平面の検知後、画面をタップした所に平面があればオブジェクトを生成するというスクリプトになります。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.iOS; public class Spawner : MonoBehaviour { public GameObject catPrefab; public float createHeight; private MaterialPropertyBlock _props; void Start() { _props = new MaterialPropertyBlock(); } void CreateCat(Vector3 position) { Instantiate(catPrefab, position, Quaternion.identity); } void Update() { if (Input.touchCount > 0 ) { var touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Began) { var screenPosition = Camera.main.ScreenToViewportPoint(touch.position); ARPoint point = new ARPoint { x = screenPosition.x, y = screenPosition.y }; List<ARHitTestResult> hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface().HitTest (point, ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent); if (hitResults.Count > 0) { foreach (var hitResult in hitResults) { Vector3 position = UnityARMatrixOps.GetPosition (hitResult.worldTransform); CreateCat (new Vector3 (position.x, position.y + createHeight, position.z)); break; } } } } } }
Meshを更新した際にPrefabが壊れてしまう問題を解決する
Unityを使用しているときによく使う機能でPrefabというものがあります。
私も普段よくPrefabを利用していますが先日このような事が起こりました。
とあるMesh(TestModel.fbxとします)を参照しているPrefab(TestModel_Prefabとします)があり。
Meshにいくつかの修正を加えMeshを入れ替えるとPrefabの表示がとんでもない事になってしまいました。
このPrefabが参照しているMeshを更新します。
すると、とんでもない事に....
この時Meshの構造、ボーンの構造に特に変更はない簡単な変更のはずなのにこのような事態になりました。
Prefabの参照元のMeshを更新できないとなると毎回Prefabを作成しないといけなくなり、参照しているPrefabが多いと大変面倒でヒューマンエラーの原因にもなりかねないです。
なんとか解決しようと詳しく調べてみるとどうもMeshの頂点番号に変更があり、UnityではMeshのもつ情報からボーンとの接続を行うらしくそれが原因らしいと分かりました。
そして色々調べて試しにこのようなScriptを作成してみると
public class ResetBoneMap : MonoBehaviour { public GameObject original; public void Convert() { SkinnedMeshRenderer[] skinnedMeshs = this.GetComponentsInChildren<SkinnedMeshRenderer>(); foreach ( var s in skinnedMeshs ) { Reset( s.GetComponent<SkinnedMeshRenderer>(), s.name ); } } void Reset( SkinnedMeshRenderer targetRenderer, string name ) { SkinnedMeshRenderer originalRenderer = getChildGameObject( original, name ).GetComponent<SkinnedMeshRenderer>(); if (targetRenderer == null || originalRenderer == null ) return; Transform[] newBones = new Transform[targetRenderer.bones.Length]; for ( int i = 0; i < originalRenderer.bones.Length; i++ ) { for ( int j = 0; j < targetRenderer.bones.Length; j++ ) { if ( targetRenderer.bones[j].name == originalRenderer.bones[i].name ) { newBones[i] = targetRenderer.bones[j]; continue; } } } targetRenderer.sharedMesh = originalRenderer.sharedMesh; targetRenderer.bones = newBones; } GameObject getChildGameObject(GameObject fromGameObject, string withName) { Transform[] ts = fromGameObject.transform.GetComponentsInChildren<Transform>(); foreach (Transform t in ts) if (t.gameObject.name == withName) return t.gameObject; return null; } }
なんと・・うまく出力されました!!
これでMeshの更新がなんとか楽になりそうです。
こちらのScriptはGithubにて公開しました。
github.com
使い方は簡単で壊れたPrefabにアタッチして元のMeshをOriginalに入れて・・・
あとはボタンを押すだけ。
処理が終われば綺麗な状態に直ります。