20210715のUnityに関する記事は5件です。

[VRC]Unityでアバターのシェイプキーの値を変えるとメッシュが消えるバグの解決法

VRCの知り合いから、この現象について質問されて、なんとか解決できたのでついでに記事にします。 解決策 Edit→ProjectSettings→Player→OtherSettings→GPUSkinningをオフにする。 これだけで動きます。 参考記事 起きた事象について 環境 Windows10 Intel Corei3 2100 3.10GHz GPU無し Unity2018.4.20f1 ミントちゃん Sunao Shader 事象 UnityでVRC用のアバターをアップロードしようとしていたところ、アバターのシェイプキー(BlendShape)の値を少しでも変えたら、そのメッシュが表示されなくなるという現象が起こりました。 そしてこの現象は、どのシェイプキーどんなアバターでも、またUnityProjectを作り直しても、またUnityEditorを再インストールしても治りませんでした。 また、このときConsoleには Platform dose not support compute shaders というエラーが表示されました。 実際に起きてるときの画像を貼ります。 シェイプキーをいじる前 シェイプキー(VRC.v.aa)の値を変えたとき シェイプキー(blink) 解決法について めっちゃ検索したところ、上で貼った参考記事が出てきて、なんとか解決しました。 記事を要約すると、GPUSkinningという機能がErrorを起こしているのが原因なので、この機能をオフにすると解決、とのことでした。 おそらく、この事象が起きたパソコンにGPUが搭載されていないことで、該当機能がErrorを起こしていたのではないかと自分は思っています。 その通りにしたら動きました。ミントちゃんもニッコニコです。 最後に GPUはいいぞ!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity 2D オブジェクトをタッチしてイベントを発生させる方法

0.0 はじめに オブジェクトをタッチまたはクリックしてイベントを発生させる方法をまとめました。 ゲーム中にキャラクタやオブジェクトをタッチして操作する際にとても便利です。 準備として何でもよいので、まずは可視出来るオブジェクトを1つ作ってください。 何もなければ、下の手順でオブジェクトが作れます。 1. 下記の青い四角を右クリック、"名前を付けて画像を保存"してください。名前は何でもよいです(例:Square.png) 2. 保存した画像をUnityのProjectウインドウ内のAssetフォルダに入れてください(ドラッグ&ドロップ)。 3. そしてこの画像をそのままHierarchyへ入れてください(ドラッグ&ドロップ)。 1.0 Event Systemオブジェクトを追加する Hierarchyの中にEvent System(イベントシステム)を追加します。忘れがちなので最初にやりましょう。 Event Systemはタッチやクリックなどのユーザー入力を監視しイベントを伝える役割を果たします。 ?ポイント Event SystemはUIを作成した際に自動的にできます。1つあれば十分なので、すでにEvent SystemがHierarchyの中にあるのであれば追加する必要はありません。 HierarchyのCreateから UI -> Event Systemの順で選んで追加します。 2.0 Physics 2D Raycasterコンポーネントをカメラオブジェクトに追加する カメラにPhysics 2D Raycasterコンポーネントを追加します。こちらも忘れがちなので最初にやりましょう。 たいていの場合、シーンにMain Cameraがあると思います(シーンの初期設定でHierarchyの中にMain Cameraが作られています)。このカメラにRaycastコンポーネントを追加します。 ?ポイント Raycast(レイキャスト)とは、ある地点から特定方向へ発射された光線(Ray)のようなもので、そのRayと衝突したオブジェクトの情報を入手することができる機能です。今回はこのRaycastの機能を使ってタッチしたところにあるオブジェクトの情報を入手します。 HierarchyでMain Cameraを選択します。そしてAdd Componentをクリックして、検索窓にてPhysics 2D Raycasterを検索して選びます。ray と入力すると予測が出てきます。 Physics Raycasterも出ますが2Dの場合はPhysics 2D Raycasterの方を選んでください。 3.0 Event Triggerコンポーネントの追加 タッチするオブジェクトを選択して、Add ComponentでEvent Triggerを追加します。Add ComponentボタンはInspector(インスペクター)の一番下にあります。  検索の窓でEvent Triggerを探します。(Eと入力すると入力予測でEvent Triggerがすぐ下に出てきます。) これでEvent Triggerコンポーネントが追加できました。 Add New Event Typeをクリックするとイベントが選べます。 ↓は Pointer Down を選んだ場合 ここへ呼び出す関数を登録します。詳しくは6.0 呼び出し関数の登録を参考にしてください。 4.0 Colliderの追加 タッチさせたいオブジェクトにコライダー追加にコライダーを追加しましょう。下の図はBox Colliderを追加したところ。 ?ポイント コライダーはBox ColliderやCircle Colliderなど数種類あります。オブジェクトの形やタッチをしたい領域に合わせて選びましょう。 2Dの場合はBox Collider 2Dのように2Dと名前が付いたものを選びましょう。 5.0 スクリプトを作成 タッチしたときの動作が書かれたスクリプトを作成します。 今回は下のようなSquare.csというスクリプトを作成してオブジェクト(ここではSquareオブジェクト)にアタッチ(貼り付け)しましょう。 Square.cs using System.Collections; using System.Collections.Generic; using UnityEngine; public class Square : MonoBehaviour { // タッチされた時に呼ばれる関数 public void OnTouched() { Debug.Log("オブジェクトがタッチされました!!"); } } 6.0 呼び出し関数の登録 右下の+を押して呼び出し関数の登録画面を作ります。 スクリプトがアタッチされたオブジェクトを"None(Object)"となっている枠に入れます(ドラッグ&ドロップします)。 "No Function"と書かれたバーをクリックしてスクリプト名、関数名を選びます。 ?ポイント 目的の関数が見つからないときは、 スクリプトが正しくアタッチされているか? 関数のアクセス修飾子がpublicになっているか? を確認してみてください。 7.0 おわりに コンソール画面に正しく表示されたら成功です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityとPython間でのデータのやり取り

背景 Unityで計測したデータをPythonに送って、機械学習で推定した結果を可能な限りリアルタイムでUnity側に反映させたかったが、調べてもサーバーを使うものしか見つからず、リアルタイムにやり取りできなかった. 目的 可能な限りリアルタイムでUnityとPythonでデータをやり取りする. UnityとPythonのコード:https://github.com/sakamo1290/DataExchange Unity:2019.4.28f1 Python:3.7.6 方針 csv(Unity2Python.csvとPython2Unity.csv)を介してデータをやり取りする. 実装 Unity側でFixedUpdateが呼び出されるたびにインクリメントされる変数(count)をcsvを介してやり取りする。 Python側 まずPython側でデータを読み書きするスクリプトを作る。 DataExchange.py #実際に使うときはやり取りするデータは1つではないため、pandasのDataFrameでcsvに読み書きする import pandas as pd def main(): #Unityから送られてきたデータを格納するDataFrame log = pd.DataFrame(columns = [0], index = [0], data = [0]) #データが更新されているかを確認するための変数 past = -1 while True: past, log = ReadData(past, log) WriteData(past) def ReadData(past, log):#Unityからデータを受け取る #データをUnityが書き込んでいるときはアクセスできずエラーになるためtryで回避 try: a = pd.read_csv('Unity2Python.csv', encoding="ms932" ,sep=",") except: return past, log #データが更新されていない場合読み取りを終了する if past == a.columns[0]: return past, log log = log.append([int(a.columns[0])]) print(a.columns[0]) past = a.columns[0] return past, log def WriteData(past):#Unityにデータを送る #Unityが読み込んでいるときはアクセスできずエラーになるためtryで回避 try: pd.DataFrame([past]).to_csv(path_or_buf = 'Python2Unity.csv', header=False, index=False) except: return if __name__ == "__main__": main() Unity側 Unity側でもデータをやり取りするスクリプトを作成する(gitのDataExchange.unitypackage内に完成したものが入れてある)。 新しいプロジェクトを作成し、ヒエラルキーで右クリックして'Create Empty'を選択する。 名前を'DataExchanger'にしてインスペクターで'Add Component'をクリックしDataExchangerスクリプトを作成する。 DataExchanger.cs using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; public class DataExchanger : MonoBehaviour { int count = 0; string sendDataPath; string recieveDataPath; void Start() { sendDataPath = Application.dataPath + "/LogData/Unity2Python.csv"; recieveDataPath = Application.dataPath + "/LogData/Python2Unity.csv"; } void FixedUpdate() { WriteData(count.ToString(), sendDataPath); ReadData(recieveDataPath); count++; } void WriteData(string data, string _filePath) { string _path = _filePath; StreamWriter sw; FileInfo fi; fi = new FileInfo(_path); sw = fi.CreateText(); sw.WriteLine(data); sw.Flush(); sw.Close(); } void ReadData(string _filePath) { Debug.Log(File.ReadAllText(_filePath)); } } DataExchange.pyを配置 Unityのフォルダ内にAssets/LogDataとなるようにLogDataフォルダを作成する。 LogDataフォルダ内にDataExchange.pyを配置する(場所はここでなくても問題ないが簡単のために。変える場合はスクリプトのパスを修正する。)。 動作確認 おおむねよく動いているが、Unity側で数字が飛ぶ場合がある。 目的は機械学習の結果をUnityに反映することであるため、推定にかかる時間を考慮すると問題ない程度であると言える。と思う。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] AdMobの広告プレースメントでモバイルアプリ内広告を実装する

はじめに AdMobのプラグインには比較的少なめのコードで広告を実装できる「広告プレースメント」という機能があります。 これによって従来の方法に比べてかなり手軽に広告を表示させられるのですが、調べてみても意外と情報が見当たらないので本記事で使い方を解説してみようと思います。 とはいえ公式ガイドもかなり読みやすく書かれているため、ガイドに沿って実装すれば基本的に問題ないと思います。そのため、本記事はどちらかというと紹介に寄せた内容となっております。困ったら公式ガイドを読みましょう。 ※広告プレースメント機能は2021/07/14時点で試験運用版となっています。 前提条件 公式ガイドに記載されている前提条件を参照。 https://developers.google.com/admob/unity/ad-placements?hl=ja https://developers.google.com/admob/unity/quick-start?hl=ja#prerequisites ただし、すでに通常のMobile Ads Unityプラグインを導入している場合は、一度消してから広告プレースメントのページの「ダウンロード」からパッケージを落としましょう。 ※プロジェクトにインポートする前に必ずバックアップを取りましょう。 筆者の環境 Unity 2020.3.1f1 (対象PlatformをAndroidとしています) Windows 10 2004 目標 バナー・インターステイシャル・リワードのテスト広告表示 解説 解説用にこのようなプロジェクトを作成しました。 「インターステイシャル」を押すとインターステイシャル広告、「リワード」を押すとリワード広告が表示されるようにします。 Assets> Google Mobile Ads> Ad Placements を開くと、インスペクタに広告プレースメントの一覧が表示されます。 インポート時に最初から入っているのは全てテスト広告になっているので、今回はこれらをそのまま使用します。本番広告にする場合はUnit IDを本番用に変えればOKです。 広告の初期化 広告を設置する前に、SDKを初期化するようにしましょう。基本的にはタイトル画面のStartなどで以下を実行させておけばOKです。 AdInitializer.cs using GoogleMobileAds.Api; using UnityEngine; public class AdInitializer : MonoBehaviour { public void Start() { // Initialize the Mobile Ads SDK. MobileAds.Initialize((initStatus) => { // SDK initialization is complete }); } } バナー広告の設置 バナー広告は従来の方法だとインターステイシャルなどより若干面倒でしたが、広告プレースメントではeditor上でサクッと実装できます。   GameObject> Google Mobile Ads> Banner Adを選択すると、ヒエラルキー上に「Banner Ad」オブジェクトが作成されます。 「AdGameObject の名前はすべて固有の名前にしてください」と書いてあるので、オブジェクト名は変えておきましょう。今回は「TestBannerAd」にしています。 インスペクタからバナーの表示形式を設定できます。今回はSizeをBanner (320×50)、Ad PositionをTopにします。 これでPlayモードにすればバナー広告が表示されます。 完 インターステイシャル広告の設置 GameObject> Google Mobile Ads> Interstitial Adを選択すると、ヒエラルキー上に「Interstitial Ad」オブジェクトが作成されます。 「AdGameObject の名前はすべて固有の名前にしてください」と書いてあるので、オブジェクト名は変えておきましょう。今回は「TestInterstitialAd」にしています。 以下のスクリプトをインターステイシャルボタンに紐づけます。 InterstitialButton.cs using UnityEngine; using GoogleMobileAds.Api; using GoogleMobileAds.Placement; public class InterstitialButton : MonoBehaviour { [SerializeField] GameObject _interstitialText; InterstitialAdGameObject _interstitialAd; private void Start() { // シーン内から広告オブジェクトを名前で取得 _interstitialAd = MobileAds.Instance .GetAd<InterstitialAdGameObject>("TestInterstitialAd"); // 広告を読み込む _interstitialAd.LoadAd(); } // インターステイシャルボタン押下時のコールバック public void OnClick() { // 広告が読み込まれていれば表示する _interstitialAd.ShowIfLoaded(); } // 広告を閉じた場合のコールバック public void OnAdClosed() { // 今回はテキストを表示する ShowText(); } public void ShowText() { _interstitialText.SetActive(true); } } 今回はStartで広告オブジェクトを取得していますが、[SerializeField]属性を使ってインスペクタから紐づけても大丈夫です。 OnClickはボタンのコールバックに紐づけておきましょう。 広告オブジェクトのインスペクタを見るとこちらにもコールバックを紐づける箇所があるので、ここに広告を閉じた場合に処理させたいメソッドを紐づけておきます。(今回はOnAdClosed) また今回はStartで明示的に広告を読み込んでいるため、自動読み込みはOffにしておきます。 これでPlayモードにし、インターステイシャルボタンを押せば広告が表示され、閉じるとOnAdClosedが実行されます。 完 リワード広告の設置 GameObject> Google Mobile Ads> Rewarded Adを選択すると、ヒエラルキー上に「Rewarded Ad」オブジェクトが作成されます。 「AdGameObject の名前はすべて固有の名前にしてください」と書いてあるので、オブジェクト名は変えておきましょう。今回は「TestRewardedAd」にしています。 以下のスクリプトをリワードボタンに紐づけます。 RewardButton.cs using UnityEngine; using GoogleMobileAds.Api; using GoogleMobileAds.Placement; public class RewardButton : MonoBehaviour { [SerializeField] GameObject _rewardText; // 広告視聴後に表示するオブジェクト RewardedAdGameObject _rewardedAd; void Start() { // シーン内から広告オブジェクトを名前で取得 _rewardedAd = MobileAds.Instance .GetAd<RewardedAdGameObject>("TestRewardedAd"); // 広告を読み込む _rewardedAd.LoadAd(); } // リワードボタン押下時のコールバック public void OnClick() { // 広告が読み込まれていれば表示する _rewardedAd.ShowIfLoaded(); } // リワード広告を最後まで観た場合のコールバック public void OnUserEarnedReward(Reward reward) { // 今回はテキストを表示する ShowText(); } private void ShowText() { _rewardText.SetActive(true); } } 今回はStartで広告オブジェクトを取得していますが、[SerializeField]属性を使ってインスペクタから紐づけても大丈夫です。 OnClickはボタンのコールバックに紐づけておきましょう。 広告オブジェクトのインスペクタを見るとこちらにもコールバックを紐づける箇所があるので、ここに広告を最後まで観た場合に報酬を受け取るためメソッドを紐づけておきます。(今回はOnUserEarnedReward) また今回はStartで明示的に広告を読み込んでいるため、自動読み込みはOffにしておきます。 これでPlayモードにし、リワードボタンを押せば広告が表示され、最後まで観て閉じるとOnUserEarnedRewardが実行されます。 今回は省略しましたが、OnAdFailedToLoadでリワードボタンを消す処理なども入れておくと良いでしょう。 完 ぱっと見ても従来に比べてコードの記述量がかなり少なくなっていると思います(バナーに至っては初期化以外ノーコード!)。コールバックもインスペクタから紐づけられるなどUnityらしい実装ができるため、とても使い勝手が良いです。 筆者は広告プレースメントを使用したアプリを1つリリースし、現在準備しているアプリでも使用していますが、特にトラブルに見舞われることなくスムーズに実装を進めることができています。現在はまだ試験運用版の機能ではありますが、アプリ内広告の実装が億劫になっている方は利用してみてはいかがでしょうか。(そして早く正式リリースされてほしいと願うばかりです)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#)】UIを画面に映さずにスクリーンショットし、ios・Androidそれぞれの写真アプリに保存

はじめに ARなどでUIを非表示にしてスクショを取りたい場面があるかと思います。 今回はいろいろ調べて下記アセットに辿り着きました。 ■ Unity Native Gallery Plugin 自前で用意することがほとんどなくなる神ライブラリだったので使い方をメモします。 バージョン情報 諸々名前 バージョン Unity 2019.4.8f1(LTS) UniTask 2.2.4 ARFoundation 4.1.1 ARCore XR Plugin 4.1.1 ARCore Kit Plugin 4.1.1 AR Subsystems 4.1.1 XR Plugin Management 3.2.16 Unity Native Gallery Plugin 1.6.4 下準備 ■ Android 「Player Settings」で「Write Permission」を「External (SDCard)」に変更します。 ■ ios どうやら、Permissionなどの記述は自動的に行ってくれるようです。 下記がProject Settingsに追加されていました。 サンプルコード using System; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UI; /// <summary> /// スクショ /// 適当なオブジェクトにアタッチ /// </summary> public class SaveScreenShot : MonoBehaviour { [SerializeField] private Button _ssButton; [SerializeField] private Camera _camera; void Start() { _ssButton.onClick.AddListener(SaveScreenShotToGallery); } private void OnDestroy() { _ssButton.onClick.RemoveListener(SaveScreenShotToGallery); } /// <summary> /// ボタンに登録するスクショ処理 /// </summary> private void SaveScreenShotToGallery() { var ct = this.GetCancellationTokenOnDestroy(); SaveScreenShotToGalleryAsync(ct).Forget(); } /// <summary> /// スクショを作成して保存する /// </summary> private async UniTask SaveScreenShotToGalleryAsync(CancellationToken ct) { //任意のフレームの描画処理が終わるまで待つ await UniTask.WaitForEndOfFrame(ct); //Cameraの描画領域をRenderTextureとして取り出す var rt = new RenderTexture(_camera.pixelWidth, _camera.pixelHeight, 24); var prev = _camera.targetTexture; _camera.targetTexture = rt; _camera.Render(); _camera.targetTexture = prev; RenderTexture.active = rt; var screenShot = new Texture2D( _camera.pixelWidth, _camera.pixelHeight, TextureFormat.RGB24, false); screenShot.ReadPixels(new Rect(0, 0, screenShot.width, screenShot.height), 0, 0); screenShot.Apply(); var date = DateTime.Now.ToString("yyyyMMdd"); //CameraのRenderTextureを元に画像を作成して保存 NativeGallery.SaveImageToGallery(screenShot, "GalleryTest", $"{date}.png" ); } } 保存先には指定した名前のアルバムが作成されます。 アプリをアンインストールしてもアルバムと写真は残ります。 任意のカメラのRenderTextureをスクショに利用しています。 これにより、Screen Space OverlayのUIはスクリーンショットに映りません。 なぜ映らないのか、それっぽい言及があったので載せときます。 The 'overlay' mode doesn't go through the normal render pipeline so it's not injected into a normal camera render. 【引用元】:https://forum.unity.com/threads/render-a-canvas-to-rendertexture.272754/ デモ 赤がWorld SpaceのUI、白がCubeです。 スクリーンショットと書かれたボタンはScreen Space OverlayのUIです。 スクショのタイミングで若干画面が止まりますが、まあ許容範囲内でしょう。 下記が実際に保存された画像です。 Screen Space OverlayのUI以外が画面に映ります。 ネイティブのUIなども映らないので通知などに邪魔されることもなく便利ですね。 おわりに 動画もUnity Native Gallery Pluginで保存できるらしいですが、 そもそも動画を書き出す処理が面倒なのでそこは自前かアセットの力を借りる必要がありそうです。 参考リンク 【Unity】iOS の写真や Andoid のギャラリーに画像や動画を保存できる「Unity Native Gallery Plugin」紹介 【Unity】スクリーンショットを保存する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む