20190607のUnityに関する記事は13件です。

クイズをランダムに出題する方法

はじめに

 こちらの記事はCSVファイルによるクイズのデータの読み込みが前提となります。CSVファイルに関しましては以下の記事をご参照ください。
 https://hakonebox.hatenablog.com/entry/2018/05/17/010407

概要

 ListRandom.Rangeを用いることでCSVファイルにあるクイズのデータをランダムに抽出、並び替えて表示します。これによりクイズゲームにおいてクイズを毎回ランダムに出題することができます。

前提

以下のようなcsvファイルをcsvDatasとして読み込んでいます。今回はここからランダムに出題していきます!

タイトル,問題,選択肢1(答え),選択肢2,選択肢3
1,世界遺産が最も多い国は?,イタリア,フランス,中国
2,「テンパる」 はどのゲームの用語から生まれた言葉?,麻雀,囲碁,ポーカー
・・・・・・・
30,次のうちJR山手線にない駅は?,汐留,田端,目白

スクリプト

まず、以下のように関数を定義します。

List<int> GetRandomList(){
        List<int> randomList = new List<int>();
        while(randomList.Count < 5){
            int y = Random.Range(1,31);
            if(!randomList.Contains(y)){
                randomList.Add(y);
            }
        }
        return randomList;  
    }

これにより、1~30の数字からランダムに5つ取り出して新たにListを作成することができるので、これを実際にListに紐づけます。

public List<int> randomQuiz;
randomQuiz = GetRandomList();

そして、この新たなListを以下のように利用してquizTextにクイズを表示させます。

quizText.text = csvDatas[randomQuiz[0]][1];

ちょっと細かい解説

以下の部分の詳しい解説をします。興味のある方だけお読みください。

while(randomList.Count < 5){
  int y = Random.Range(1,31);
  if(!randomList.Contains(y)){
    randomList.Add(y);
  }
}

1行目はrandomListの要素数が5個になるまで以下の処理を続けるという意味です。
2行目はRandom.Rangeを利用して、1~30のうちランダムに1つの数をyに代入するという意味です。
3,4行目はもしrandomListの要素に上で代入したyが含まれていなければ新たにyをrandomListに追加するという意味です。3行目の条件があることで数字の被りを防止しています。

終わりに

今回紹介したランダムな数字のListを作成する方法はクイズだけでなく様々な場面で活用することができると思います。ぜひ応用してみてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

滑らかな左右の移動

今回は僕が実際に作ったレースゲームを例に挙げCoroutineとIEnumeratorの使い方について紹介していきます。

レースゲームの概要

コースはレーンになっており、ボタンも押すと隣のレーンに滑らかに移動できるようになっています。
はじめの移動は早く、最後はゆっくり動くようにしました。
gihなので少し滑らかさ無いように見えますが、もっと滑らかに動きます。

Qiita用.gif

Coroutine

コルーチンとは『フレームを跨いで処理を中断・再開させることが出来る仕組み』です。
例えば、通常for文の繰り返し処理30回を処理しようとすると、30回の処理を全て同じ1フレームで行います。
これをコルーチンを用いることで、30回の処理を30フレームなど分けて処理することができます。

ゲームのコード

十字キーのRightキーを押した時の処理を取り上げてみます。

RightKeyを押したら、(Horisontal1)というコルーチンを実行します。

void Update ()
    {
        float pos_x = transform.position.x;

        if (Input.GetKeyDown (KeyCode.RightArrow)) {
            if (pos_x < 4) {
                StartCoroutine(Horizontal1());
            }
        }
    }

for文の処理回数はiが10の時、9の時、8の時、...1の時まで10回の処理があります。
この10回の処理で3.7右に移動したいです。

3.7の距離を55等分して、iが10の時55等分のうち10だけ右に移動する、次はiが9の時55等分のうち9だけ右に進む、その次はiが8の時....とやっていくと丁度10回の処理で3.7右に進むことができます。
これで徐々に進む距離が減っているので最初は早く、最後はゆっくり進むことができました。

private IEnumerator Horizontal1()
   {
        for (int i = 10; i > 0; i--) {
            float p = i * 3.7f / 55;
            Vector3 nowPos = transform.position;
            transform.position = new Vector3 (nowPos.x + p, nowPos.y, nowPos.z);
            yield return null;
         }
     }

スクリーンショット 2019-06-13 16.03.35.png

また変数pを下のようにする事で等速で左右に移動したり、for文の条件を変える事で徐々に早く動くようにもできます。

float p = 3.7f / 10;
for(i = 1; i <11; i++)

これは『ここまでで1フレーム』という意味の文です。

yield return null;

また上の文を下のようにすることで1フレームだけでなく指定した数秒ごとに実行することができます。

yield return new WaitForSeconds(秒数);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VRchatのワールド上に自分の脈絡数をグローバルで表示する

arduinoと脈拍センサを使って、VRchat上に自分の脈拍数を公開する
脈拍デバイス作成についてまとめました。
ハードウェアなので電子工作とプログラミングが必要になりますが、
未経験の人でもわかりやすいよう、噛み砕いて書いていきたいと思います。

デバイスを作成せず、ワールドに脈拍表示器を置きたいという人は、
自分のワールドに脈拍表示器を設置するを参照してください。

注意

この方法はVRchatに実装されているVRC_MidiNoteInを使って実現しています。
ardiunoにプログラムを書き込んだ時点で、MIDI機器としてPCの環境に干渉します。
また今後VRchatのアップデートによっては、この方法は使えなくなる可能性があります。
前例↓
https://vrchat.canny.io/bug-reports/p/vrcoscbuttonin-is-not-working

事前準備(ハードウェア)

・Arduino Leonardo or Arduino Pro Micro 5V,16MHz
お手軽マイコンボードのArduino Leonardo
ハンダ付けが可能な環境であれば、
安くて小型なArduino Pro Micro 5V,16MHzもお勧めします。

Arduino Leonardo
https://www.switch-science.com/catalog/968/
Arduino Pro Micro 5V,16MHz
www.amazon.co.jp/dp/B01M6WULAO

・脈拍センサ
ハートマークが印刷されているセンサモジュール
ハートマークの面を耳たぶや指先に着けると、脈拍の動きを波形でアナログ出力します。
耳たぶクリップやマジックテープのセット
https://www.switch-science.com/catalog/1135/

色々なメーカーが似たようなのを作っているので、
耳たぶクリップが要らなければamazonで安く買えます。
www.amazon.co.jp/dp/B07H2F2TYT

海外通販に抵抗がなければ、
aliexpressやebayなどを利用するのもアリです。

品質はそれなりで、届くのも2~3週間ほどかかりますが、
Arduino Pro Microと脈拍センサの耳たぶクリップ付きセットを
合わせて6,7ドル程度で購入できます。

Arduino Pro Micro
https://ja.aliexpress.com/item//32768308647.html
https://ebay.to/2wA2mfG

脈拍センサキット
https://ja.aliexpress.com/item//32603915428.html
https://ebay.to/2JRwkob

・USBケーブル2.0 Micro-B
よくある通信用USBケーブル
arduinoとPCを通信するために使います。

配線作業

Arduino Leonardoと脈拍センサーを以下の画像のように接続します。

pp.jpg

配線の色が違う!という場合は脈拍センサに書かれている記号を確認して
S = A0
+ = 5V
- = GND
とarduino側に配線します。

Arduino Pro Microの場合は以下のように半田付けしてください。
このデバイスはUSBの5Vから電源をもらうので、
基板上のJ1と書かれている箇所(赤丸)を半田で埋めてください。
(埋めたら今後、このPro Microの電源に5V以上の電圧をかけないで下さい。)

ppa.jpg

*注意*
配線ミスやショートに気をつけてください。
arduino側にはヒューズがついていますが、
ショートした際、運が悪いとICが焼損し、
更に運が悪いとUSBポートにダメージが及ぶこともあります。

ハードウェアはこれで完成です。
脈拍センサは基板としては剝き出しなので、
金属などでショートしないよう扱いに注意して下さい。
私はグルーガン(黒)で保護しました。

事前準備(ソフトウェア)

・Unity 2017.4.15f1
・VRChat SDK (最新)

・Arduino IDE
Arduinoのプログラム(スケッチ)を書いて、ボードに書き込むソフトウェアです。
Arduino Software https://www.arduino.cc/en/main/software

・VRC_MIDI_Pulse
脈拍センサから受け取ったアナログ値をAD変換し、
デジタル値に変換した値をMIDIデバイスとしてVRchatへ送信するプログラムになります。
clone or downloadからダウンロードしてください。
https://github.com/Ryou328/VRchat_midi_pulse_sensor

・脈拍表示器
表示はブタジエンさん作のCalulater and numberを使用させて頂きました。
https://twitter.com/butadiene121/status/1001489400860037122

MITライセンスということなので私がMIDI用に設定済みのprefabを同梱した、
Calulater and numberのunitypackageをアップしましたので以下からダウンロードしてください。

https://drive.google.com/file/d/1kLlJzsBbhQEg4So-B7Ar9bgcLZxq11mc/view

*2019.6.9 prefabの構成にミスがあったので修正しました。
既にインポートされた方はお手数ですが、midi_numberの中身を差し替えて下さい。

ソフトウェア導入

Arduino IDEのインストーラー版をダウンロードし、インストールします。
4.jpg
インストールはNEXT連打でOKです。

インストール後、arduinoとPCをUSBで接続してください。
この時、脈拍センサとarudinoのLEDが点灯していることを確認して下さい。
点灯していない場合、配線ミスかショートしている可能性があるので、
素早くUSBを抜いて配線を確認します。

問題無い場合、arduinoドライバのインストールが始まるので完了するまで待ちます。

完了したらArduino IDEを起動し
メニューの[ツール]→[ボード]→[Arduino Leonardo]を選択し、
[シリアルポート]→[COM XX(Arduino Leonardo)]を選択してください。
画像のCOM番号は40ですが、番号は個々のPC環境によって変わります。

1.jpg

正しく認識されていれば、[ボード情報を取得]をクリックすると
接続されているArduino Leonardoの情報が表示されます。

Arduino Pro Microで接続した場合でも、Leonardoとして認識されます。
(自分をLeonardoだと思いこんでいるPro Micro)

必要なライブラリを揃える

メニューの[スケッチ]→[ライブラリをインクルード]→[ライブラリを管理]をクリックし、
ライブラリマネージャを起動します。
検索欄で「MIDIUSB」と検索して、出てきたMIDIUSBの最新verを選択し、
インストールします。
2.jpg

同じように「pulsesensor」で検索し、最新verをインストールします。
*筆記時、MIDIUSBver_1.0.4、pulsesensor_ver1.5.0

ファームウェア書き込み

arduinoにファームウェアを書き込みます。
githubからをダウンロードしたVRC_MIDI_Pulseを解凍し、
VRC_MIDI_Pulse.inoをarduinoで開きます。

[スケッチ]→[マイコンボードに書き込む]をクリックし、しばらく待ちます。
エラーが出た場合は必要なライブラリを見直してください。
[ボードへの書き込みが完了しました。]と出れば成功です。
3.jpg

この書き込み後、シリアルポート番号が変化する場合があるので、
[ツール]→[シリアルポート→COM ??(Arduino Leonardo)]を選択し直してください。

脈拍センサの緑色に光っているハート面を指先か耳たぶに装着し、
[ツール]→[シリアルモニタ]をクリックすると、
現在の脈拍数であるBPMとMIDI用に変換された三行の数字が表示されるはずです。

32.jpg

しばらくしてもBPMが0だったり、安定しない場合は装着を見直して下さい。
それでもおかしい場合は、基板が壊れている場合があります。
(aliexpressで買った脈拍センサがハズレだった経験談)

この状態でVRchatを起動し、テストとして私のワールドにインしてみましょう。
https://vrchat.net/home/launch?worldId=wrld_12a18d9e-c431-4d57-84e0-894753d16d52

脈拍数が表示されて変動していれば成功です。
20190608124648_1.jpg

うまく動作しましたらTwitterなどで報告して頂けると私が大変喜びます。

自分のワールドに脈拍表示器を設置する

googleドライブからダウンロードした脈拍表示器のunitypackageをunityにインポートしてください。

prefab→midi_numberフォルダにあるch12のプレハブを好きな場所に設置して完了です。
wereseg.jpg

複数設置したい場合はMIDIのch(チャンネル)が被らないようプレハブを設置して下さい。
またそのチャンネルに合わせたデバイスの書き換えも必要なので、
MIDIチャンネルの書き換えを参照して下さい。

MIDIチャンネルの書き換え

デフォルトのVRC_MIDI_PulseのMIDIチャンネルは12を指定しています。
チャンネルが被ると正しく動かないので、VRC_MIDI_Pulseの12行目の
const uint8_t MIDI_CH = 12;
の12の値を1~15のいずれかに被らないよう設置したprefabのチャンネルに合わせて、
値を変更してarduinoに書き込んでください
0は指定しないで下さい。すべての表示器に適応されてしまいます。

脈拍センサデバイスの装着について

VIVEのHMDにはUSBハブの空きポートがあるので、今回作成したデバイスを接続しても認識します。
この空きUSBに接続して耳たぶに脈拍センサーを装着すれば、
moveやダンスをする際、配線を気にせず動くことができます。

Oculusについては持っていないので検証出来ないのですが、
聞いた話だとHMDに空きUSBポートが存在しないらしいので、
上記の耳たぶ装着はviveより難しくなると思われます…

私の環境はVIVEにTPcastを使っていましたが、これだとTPcast以外のUSBは認識されないので、
OpenTPCastを導入した上で、VirtualHereを使ってをarduinoを認識させています。
D8CIFOKUEAAvdW6.jpg

コンパクトにしたやつ
もし売るとしたらこんな感じになると思います。
CIMG0801.JPG

仕組み

arduino側
脈拍センサで取得したBPM値を各桁ごとに分けます。
例として死にますがBPMが12だった場合三桁表示なので、
0,1,2
という感じで分けます。
分けた値をMIDIのnote番号に変換します。

VRchatSDKのVRC_MidiNoteInはピアノで使う前提として、
作られているらしくMIDIのnoteは21~108でとなっています。

今回は独自にnoteと数値を割り当てましたが、
割り当て方は単純にunityのVRC_MidiNoteInコンポーネントにある、
noteの一番上から順番にA0=0,Bb0=1,B0=2と割り当てました。

A0のnote番号は21なので、0=21,1=22,2=23として変換してます。
変換した三桁分のnote番号をPCに接続されたmidiデバイスとして送信します。

VRchat側
各桁のCalulater and numberの入力用オブジェクトを
受信したnote番号に合わせてVRC_MidiNoteInがトリガーを引くことにより、
その番号が表示されます。

実際のウェアラブル的な脈絡計としては結構いい感じです。
個人的には指より耳たぶの方が安定しています。
更新速度は1秒くらいでVRchat側にも負荷はほとんどないと思われます。
ダンス中でも値は取れますが時々値が飛んだりするので、
やっぱり安静時が一番精度が出る感じです。

最後に

今回は電子工作をしたことない人向けに書いてみたのでちょっと冗長気味になりました。
VRC_MidiNoteInを使ったこの方法は色々と応用が効きそうなので、
脈拍に限らず色々なセンサーを接続して、
現実とVRchatとで色々なやり取りをしてみると面白いと思います。

もし、作るの面倒!でも欲しい!という方がおられれば、
完成品をboothとかで出品してみようかな…

次は書く書くといってずっと放置しているDTMF音源を使った、
VRchat→外部機器の通信をまとめる…はず…かも

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityAdMobPluginアプデ時のエラー対処方法

はじめに

AdMobプラグインアップデート後に以下のエラーがiOS/Android共に発生

The Google Mobile Ads SDK was initialized incorrectly

実装環境

  • Unity 2019.1.4f1
  • Google Mobile Ads Unity Plugin v3.17

対処方法

AppIDの設定箇所が重複しているため、以下のファイルの該当部分をコメントアウト
もしくはAppIDをセットする

iOS

GoogleMobileAds/Editor/PListProcessor.cs
using System.IO;

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;

public static class PListProcessor
{
    [PostProcessBuild]
    public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
    {
        // Replace with your iOS AdMob app ID. Your AdMob App ID will look
        // similar to this sample ID: ca-app-pub-3940256099942544~1458002511

        //以下の部分をコメントアウト
        /*
        string appId = "ADMOB_APPLICATION_ID";

        string plistPath = Path.Combine(path, "Info.plist");
        PlistDocument plist = new PlistDocument();

        plist.ReadFromFile(plistPath);
        plist.root.SetString("GADApplicationIdentifier", appId);
        File.WriteAllText(plistPath, plist.WriteToString());
        */
    }
}

Android

Plugins/Android/GoogleMobileAdsPlugin/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
This Google Mobile Ads plugin library manifest will get merged with your
application's manifest, adding the necessary activity and permissions
required for displaying ads.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.unity.ads"
    android:versionName="1.0"
    android:versionCode="1">
  <uses-sdk android:minSdkVersion="14"
      android:targetSdkVersion="19" />
  <application>
    <uses-library android:required="false" android:name="org.apache.http.legacy"/>
    <!-- Your AdMob App ID will look similar to this sample ID: ca-app-pub-3940256099942544~3347511713 -->

<!-- 以下の部分をコメントアウト -->

<!--    <meta-data
    android:name="com.google.android.gms.ads.APPLICATION_ID"
    android:value="[ADMOB APPLICATION ID]"/>
 -->
  </application>
</manifest>

参考リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity初心者でも!数学苦手でも!角度のQuaternion表現を理解したい!!

はじめに

最近Unityをはじめました。前からCADさわったりはしていたので,3次元の概念については余裕だろ〜と思っていました。
なんですかQuaternionって。
パラメータが4つってどういうことですか。
リファレンスを読んでも

クォータ二オンは複素数に基づいており、直感的に理解するのは容易ではありません。個々のクォータニオンの成分 (x,y,z,w) にアクセスしたり変更したりすることはほとんどありません。たいてい、既存の回転 (例えば、Transform から取得) を使用して新しい回転を構築するために使用します (例えば、2 つのローテーションの間を円滑に補間するなど)。使用する Quaternion 関数の 99% は、Quaternion.LookRotation、Quaternion.Angle、Quaternion.Euler、Quaternion.Slerp、Quaternion.FromToRotation、Quaternion.identity です (他の関数が使用されることはほとんどありません)。

とあり,「サジ投げとるやないかい!」と思ったのでめっちゃ頑張って勉強しました。
間違っていたらあたたかく指摘していただけると嬉しいです:innocent:
(ちなみに私は一応理系なので語彙があれな時はまあそういうことです)

参考

本記事はを書くにあたって以下の記事で勉強しました。
ありがとうございます:pray:

超ざっくり複素数平面

詳しい人に怒られそうな感じでやっていきたいと思います!(高校数学だしいけると思うので)
わかる方はこの項目飛ばして大丈夫です。
平面上の任意の点を表現するとき,以下のような座標の表現をします。

P(x座標, y座標)

スクリーンショット 2019-06-07 19.12.32.png
複素数平面では,この時のx軸を実軸,y軸を虚軸として以下のような表現をします。

P(実軸の座標, 虚軸の座標 i)\\
(iは虚数単位)

スクリーンショット 2019-06-07 19.19.39.png
この虚数平面上に,半径1の円があると考えます(単位円)。
この円周上にある点は以下の複素数で表現することができます。

\cos\theta+i\sin\theta\\
(iは虚数単位)

スクリーンショット 2019-06-07 19.26.13.png
ここで,実部が0の複素数iが表現する点を考えます。iθ=90°の位置の点を表現しています。
このiにさらにiをかけると

i\times i = -1

となります。このとき,-1が表現する点を考えると単位円上のθ=180°の点になります。
さらにiをかけると-iとなり,この点が表現する点は単位円上のθ=270°の点です。
図に示すとこんな感じ。
スクリーンショット 2019-06-07 19.56.12.png
つまり,単位円上の点を掛け合わせること=回転角を足すことになります。

平面から立体へ

アイルランドの数学者ウィリアム・ローワン・ハミルトンは(たぶん)考えました。これを三次元空間の力学に応用できないか。
これによって生まれたのがQuaternionです。
虚数で3次元空間を表現するために,ハミルトンは虚数単位を3つ作って解決しました。(本記事ではijkとします)
この虚数単位は以下のようなものであると定義されました。

i^2=-1, j^2=-1, k^2=-1\\
ij=k, ji=-k\\
jk=i, kj=-i\\
ki=j, ik= -j\\
ijk=-1

虚数単位が3つにふえた複素数は以下のような数として表現できます。

ix+jy+kz+w\\
(x,y,z,wは実数)

そしてこれは(x,y,z)の向きにw進んだ位置(ベクトルの大きさ)の点を示します。
スクリーンショット 2019-06-07 20.35.38.png
これらの係数をまとめたものをQuaternionとしました。
(つまりQuaternionは本来回転を示すものではないです)

Quaternion=(x, y, z, w)

これに以下の条件を付与することで回転に限定して考えられるようになります。

x^2+y^2+z^2+w^2=1

回転したい!

先ほど,単位円上の点を掛け合わせること=回転角を足すことという話をしました。
つまりQuaternionをいい感じにかけたら回転ができるのではないか…
では以下の点PV分だけ回転させた点P'を考えていきます。実部はベクトルの大きさを示すパラメータなので,Vの実部は0です。
ここで,実部の係数が0のQuaternionをpure quaternionと呼びます。

P=p_1i+p_2j+p_3k+p_4\\
V=v_1i+v_2j+v_3k+0

ではいざかけてみましょう!
となりましたが純粋にPVをかけても回転後のPの角度は求められません…
なぜなら実部が残ってしまうから。これを消すために,以下のように計算すると,wが0になって,計算結果がpure quaternionになります。

P'=PVP

こうするとうまく回転します。

おわりません

虚数単位が3つある複素数は以下のように表現できるという話でした。

ix+jy+kz+w\\
(x, y, z, wは実数)

しかし,虚数単位が1つだった時cosθ+isinθと表現したように,θを使おうとしたときに問題が発生します。
Pを2回かけているので最初の位置がθではなくになっています…
ということでθを2分の1して,以下のような表現になります。

\cos\frac{\theta}{2}+(ix+jy+kz)\sin\frac{\theta}{2}

完全に理解した…:innocent:

結論

Quaternion.AngleQuaternion.Eulerを使おう。
UnityのrotationをQuaternionで直接いじりたくて勉強しましたが,私には無理だということがわかりました…
大人しくQuaternion.Angleでオイラー角に直してからQuaternion.EulerでQuaternionに戻します…
ありがとうございました:wave:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

固定長レイマーチで関数表示(ShaderLab)

目的

レイマーチを試したのでその備忘録

固定長進行レイマーチングやってみた
本記事はこのサイトにあるコードをちょっといじったものになります

やること

Unityでレイマーチングのシェーダーを書いて z = f(x,y) の形の関数を表示させる

レイマーチングとは

光の経路を逆算して描画する方法
詳しくは他の記事参照
今回は本来のレイマーチングとは違って固定長でレイを進める

実装

球を表示する

sphere.png

sphere.shader
Shader "Custom/RayMarching/Sphere"
{
    Properties
    {
        _Threshold("Threshold", Range(0.0,3.0)) = 0.6   // 閾値
        _Color("Color", Color) = (1.0,1.0,1.0,1.0)      // 表面の色
    }
    SubShader
    {
        Tags{ "Queue" = "Transparent" }
        LOD 100

        Pass
        {
            ZWrite On
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 pos : POSITION1;
                float4 vertex : SV_POSITION;
            };

            // vert関数は本題ではないので簡潔に
            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.pos = mul(unity_ObjectToWorld, v.vertex);
                o.uv = v.uv;
                return o;
            }

            float _Threshold;
            fixed4 _Color;

            // 今の位置が球の内部かどうか
            bool IsInObject(float3 pos)
            {
                return distance(pos, float3(0.0, 0.0, 0.0)) < _Threshold;
            }

            // ライティング(Lambert)
            float LightingObject(float3 pos)
            {
                return saturate(dot(normalize(pos),_WorldSpaceLightPos0));
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col;

                // 背景は透明に
                col.xyz = 0.0;
                col.w = 0.0;

                // レイの初期位置(表面上)
                float3 pos = i.pos.xyz; 

                // レイの進行方向
                float3 forward = normalize(pos.xyz - _WorldSpaceCameraPos); 

                // 一定の割合でレイが進行
                // オブジェクト内に到達したら光の計算
                // 当たらなかったら色変更なし(透過)
                const int StepNum = 2000;
                const float MarchingDist = 0.03;
                for (int i = 0; i < StepNum; i++)
                {
                    if (IsInObject(pos))
                    {
                        col.xyz = _Color.xyz * LightingObject(pos);
                        col.w = 1.0;
                        break;
                    }
                    pos.xyz += MarchingDist * forward.xyz;
                }

                return col;
            }
            ENDCG
        }
    }
}

単純に球を表示するだけです
_Thresholdで球の半径を
_Colorで球の色を指定できます
画像では色を空色っぽく変更しています

// ライティング(Lambert)
float LightingObject(float3 pos)
{
    return saturate(dot(normalize(pos),_WorldSpaceLightPos0));
}

球の表面の法線は球の中心から見た点方向のベクトルなので、それとワールドにある平行光線の方向の内積を取ることで陰を表現できます
詳しくは「Lambert反射」を調べてください

関数を表現する

初めの方で言った関数です
sinsin.png

Function.shader
Shader "Custom/RayMarching/Function"
{
    Properties
    {
        _Threshold("Threshold", Range(0.0,3.0)) = 0.6 
        _Color("Color", Color) = (1.0,1.0,1.0,1.0)
        _Ambient("Ambient", Color) = (0.0,0.0,0.0,0.0)
    }
    SubShader
    {
        Tags{ "Queue" = "Transparent" }
        LOD 100

        Pass
        {
            ZWrite On
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           #pragma multi_compile_fog

           #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 pos : POSITION1;
                float4 vertex : SV_POSITION;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.pos = mul(unity_ObjectToWorld, v.vertex);
                o.uv = v.uv;
                return o;
            }

            float _Threshold;
            fixed4 _Color;
            fixed4 _Ambient;



            float Func(float x, float z){
                return sin(x) + sin(z);
            }

            float3 CalcNormal(float2 pos){
                const float delta = 0.00001;
                float x = pos.x;float z = pos.y;
                float dx = Func(x + delta,z) - Func(x - delta, z);
                float dz = Func(x, z + delta) - Func(x, z - delta);
                dx /= delta;
                dz /= delta;
                return normalize(-float3(dx,-1,dz));
            }

            bool isInObject(float3 pos) {
                return pos.y < Func(pos.x,pos.z);
            }

            float LightingObject(float3 pos){
                return saturate(dot(CalcNormal(pos.xz),_WorldSpaceLightPos0));
            }
            fixed3 ColorDefine(float3 pos){
                float lightRate = LightingObject(pos);
                return _Color.xyz * lightRate + _Ambient * (1 - lightRate);
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col;

                col.xyz = 0.0;
                col.w = 0.0;

                float3 pos = i.pos.xyz; 

                float3 forward = normalize(pos.xyz - _WorldSpaceCameraPos); 

                const int StepNum = 2000;
                const float MarchingDist = 0.03;
                for (int i = 0; i < StepNum; i++) {
                    if (isInObject(pos)) {
                        col.xyz = ColorDefine(pos);
                        col.w = 1.0;
                        break;
                    }
                    pos.xyz += MarchingDist * forward.xyz;
                }

                return col;
            }
            ENDCG
        }
    }
}

関数では球ほど簡単には法線を計算できないので、それ専用の関数を作っています

float3 CalcNormal(float2 pos){
    const float delta = 0.00001;
    float x = pos.x;float z = pos.y;
    float dx = Func(x + delta,z) - Func(x - delta, z);
    float dz = Func(x, z + delta) - Func(x, z - delta);
    dx /= delta;
    dz /= delta;
    return normalize(-float3(dx,-1,dz));
}

関数

z=f(x,y)

の、点(a,b,f(a,b))での法線は

(f_{x}(a,b),f_{y}(a,b),-1)

と表わされ、fx,fyはそれぞれdx,dyに対応しているわけです
ただしここで2点注意しなければいけないことがあって
一つはUnityはy軸が上方向なので式中のyとzを入れ替えなければならないこと
二つ目は実際の法線は逆方向なので-1をかけなければならないこと
それを考慮すると上記の関数ができます

Func関数の中身をいじれば別の関数を表示することもできます

まとめ

レイマーチングだと関数を正確に表現できるのでどこかで使えそう(適当)
関数次第でどんな図形も表現できるのは素晴らしいと思います

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】上下にゆらゆら動くアイテムボックスをつくる


Unityでゲーム開発をしているときの
あーこういうの欲しいな!を叶える、
知っていれば確実にゲームに彩りを加えられるメソッドを紹介します。

PingPong関数

この記事で紹介するのは
ゲーム内によくある、上下にゆらゆら動いているアイテムボックスなどに使える
PingPong関数です。

Mathf.PingPong(時間, 上下差)


この関数では その名の通り、
0と「上下差」で指定した数値の間を、ピンポン球のように行ったり来たりする値を取得できます。

Mathf.PingPong(time.deltaTime, 10);

このようにすれば、0~10の値が返ってきます。

アイテムボックスを動かす

上下に移動するアイテムボックスはy軸方向に動いているので
PingPong関数をy座標に使います。



まず、次のように書いてみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class itemBoxScript : MonoBehaviour { 

    public float nowPosi;

    void Start () {
        nowPosi = this.transform.position.y;
    }

    void Update () {
        transform.position = new Vector3(transform.position.x, nowPosi + Mathf.PingPong(Time.time, 0.3f), transform.position.z);
    }

}


再生開始と同時に最初のアイテムボックスのy座標(nowPosi)を取得しておきます。
でないと、Mathf.PingPongだけでは

(y座標) = 0 + (上下させたい値)

になってしまうので、
オブジェクトをシーンビューでどのようにおこうとも
開始と同時にy=0の周辺で上下するようになってしまいます。



次に
取得したy座標にMathf.PingPongで上下させたい値を足します。

x座標、z座標には最初の座標をそのまま反映させましょう。



するとこんな感じ。

pingpongそのまま.gif

なんだか上下の動きが激しい気がするので
Mathf.PingPongのところを

Mathf.PingPong(Time.time/3, 0.3f)


このように変えてみると

pingpong:3.gif

ゆっくりになりました。

まとめ

  • 再生開始時の座標を取得する
  • Mathf.PingPongはゆらゆら移動してほしい向きの座標に足す


上下に動くアイテムボックスが完成しました!


参考

Unityスクリプトリファレンス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

using UnityEditor; を含むDLLを作るときに気をつけること

はじめに

コード保護などのためにC#スクリプトをDLL化する人向けの記事です。
DLLの中にusing UnityEditor;を含むスクリプトが書かれており、それが原因でビルドが通らないことがあったので、
備忘録がてらまとめます。

起きたこと

iOSビルドが通りませんでした。エラーログを見ると

ArgumentException: The Assembly UnityEditor is referenced by Hoge.Hoge
 ('Assets/Plugins/Hoge.Hoge.dll'). But the dll is not allowed to be included or could not be found.

が出力されていました。(ログは簡略化しています)
Hoge.Hoge内でUnityEditorの参照が必要だけどDLLが見つからないか、ビルドに含めることが認められてなかったよ
という旨のログです。

原因・考察

これの原因は
Hoge.Hoge.DLL内でエディタ拡張のコードを書いていたことです。
今回書いていたコードはAttributeの拡張で、自作属性を宣言していました。

PathAttributeDrawer.cs
[CustomPropertyDrawer(typeof(PathAttribute))]
public class PathAttributeDrawer : PropertyDrawer
//以下略

インスペクタ上にドラッグアンドドロップでフォルダのパスを指定できるエディタ拡張です。
参考:Inspectorにファイルをドラック&ドロップしてパスを設定する
PropertyDrawerがUnityEditor下のコードで、UnityEditorを読み込む必要がありました。

本来ならばエディタ拡張のスクリプトはEditorディレクトリに設置するものです。
しかし今回はDLLで包んでいるので、該当コードがPluginsディレクトリに存在する扱いになっていました。

Editorディレクトリはビルド時は自動的に除外され、ビルドに含まれることはありません。
そのためUnityEditorを参照するスクリプトを置いてあってもエラーは発生しませんでした。
今回はPluginsディレクトリに存在したため、全てのコードがビルドに含まれてしまい、
本来ならば弾かれるべきコードが弾かれず、エラーを吐いてしまいました。

対策

ビルド時に自動的に弾いてくれないので、スクリプト側で自分から弾かれるように
プラットフォーム依存コンパイルで区切りましょう。#defineディレクティブです。

UnityEditorで実行するときだけ走り、ビルドで走らなくするための#defineは
#if UNITY_EDITORです。
今回書いたスクリプトは1クラス1ファイルのエディタ拡張のみのコードなので、全てを囲んでしまいました。

PathAttributeDrawer.cs
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;

//中略

#endif

#defineで囲んだことでUnityEditor外の環境ではコードが走らなくなり、
Pluginsディレクトリに存在してもコンパイルされなくなりました。
これでエラーが出ずにビルドが通るようになりました。

結論

Editorディレクトリ以外にエディタ拡張のスクリプトを設置すると、
ビルド時にUnityEditorの参照が足りなくなりエラーが出て通りません。
DLL化してPluginsディレクトリに設置するとき(以外のケースもあるかも?)等、
エディタ拡張コードをEditorディレクトリ以外に置くときは、
スクリプト丸ごと#if UNITY_EDITORで囲んでコンパイルが走らないようにしましょう。

さいごに

対策方法を教えてくださったアズマゴローさんありがとうございました!!


おかげさまで仕事が進みます。助かりました。
ここまで読んでくださった皆様もありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AppStoreConnectアップロード時、'UIApplicationExitsOnSuspend'の警告が出る件

概要

AppStoreConnectアップロード時、iOS13でUIApplicationExitsOnSuspendのサポートがなくなるので、非推奨だよというメッセージが出るようになりました。

WARING ITEMS-90339 "Deprecated info.plist" Key. The Info.plist contains a key 'UIApplicationExitsOnSuspend' in bundle myapp [myapp.app] that will soon be sunsupported.

iOS13のリリースノート iOS & iPadOS 13 Beta Release Notes | Apple Developer Documentation

問題

UIApplicationExitsOnSuspendはアプリのバックグラウンド実行を禁止する機能ですが、デフォルトだとNOだと思うので、大体のアプリは消せばOK。

Deprecations
The UIApplicationExitsOnSuspend key is no longer supported in iOS & iPadOS 13. Update your apps to handle modern multitasking. (43958234)
※リリースノートから引用

「バックグラウンド実行を無効化出来なくなるのでマルチタスク処理をしていない人はやってね」と言われているので、無効化設定している人はバックグラウンド処理を改修する必要がありますね。

解決方法

Waringが出るだけで、アップロード自体は出来るが、警告出てるのも気持ち悪いし、リジェクトされたら嫌なので対応しました。

とりあえず、plist.infoからApplication does not run in backgroundの項目をDeleteすればOK。

Unityからは現状、自動的に追加されてしまうので、ビルドスクリプト(PostProcessBuildなど)を用いてUIApplicationExitsOnSuspendを削除するのが良さそう。フォーラムにサンプルコードが投稿されています。

Unityフォーラムページ The Info.plist contains a key 'UIApplicationExitsOnSuspend

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

uGUIでスマホUIの作成

概要

Unityのバージョンは5.2.3f1

uGUIでスマホのUIを作るためのメモです。(投稿忘れてた古い情報なので注意)
スマホのUIの参考サイト
http://nvtrlab.jp/blog/jb/ios_ui_component.html
http://growthhack.sirok.co.jp/growth-message/in-app-message/
http://raksul.com/magazine/10120_統一感のある、ハイクオリティな無料UIデザインキット40個まとめ.html/
http://titanium-sdk.net/dic/views/?type=V
http://greety.sakura.ne.jp/redo/2011/06/10androidui.html

投稿予定
ドロップダウンの作り方
スライドスイッチの作り方
サークルスライダーの作り方
レーティングの作り方
インジケータの作り方
ピッカーの作り方
リストビューの作り方
モーダルメッセージウィンドウの作り方
ウィンドウシェードの作り方
アクションパネルの作り方
タブナビゲーションの作り方
セグメンテッドコントロールの作り方
スワイプナビゲーションの作り方
リストページャーの作り方
スライドメニューの作り方

親オブジェクトのImageにTextの文字サイズを合わせる方法

  1. ImageとTextを追加してTextをImageのこオブジェクトにする
  2. TextのAnchor Presetsの一番右下をAltとShiftを押しながら選択
  3. TextのBest Fitにチェックを入れてMax Sizeを調整する

文字サイズに合わせて高さと幅を変更

(Content Size Fitterを使用)
1. TextにAdd Component>Layout>Content Size Fitterを追加
2. Content Size FitterのHorizontal FitとVertical FitをPreferred Sizeに設定

Buttonサイズに合わせて文字の高さと幅を変更

(Aspect Ratio Fitterを使用)
1. Buttonを追加してTextにAdd Component>Layout>Aspect Ratio Fitterを追加
2. TextのBest Fitをチェックする
3. Aspect Ratio FitterのAspect ModeをWidth Controls Heightに設定
4. Aspect Ratioの値を調整してボタンとテキストの余白を調整
同様にToggleも拡大縮小した時にチェックイメージとテキストサイズが自動で調整されるものを作ることができるかも

文字サイズの違うTextを縦に並べて表示

(Vertical Layout Group、Content Size Fitterを使用)
1. 空オブジェクトを作って、子オブジェクトにTextを何個か追加
2. 空オブジェクトにAdd Component>Layout>Vertical Layout Groupを追加
3. 空オブジェクトにAdd Component>Layout>Content Size Fitterを追加
4. Content Size FitterのHorizontal FitとVertical FitをPreferred Sizeに設定

ボタンを横に並べて表示

(Horizontal Layout Groupを使用)
1. 空オブジェクトを作って、子オブジェクトにButtonを何個か追加
2. 空オブジェクトにAdd Component>Layout>Horizontal Layout Groupを追加
3. Horizontal Layout GroupのSpacingでButton同士の間に余白をつける

ボタンを横に並べて表示した時、サイズを個々に調整する

(Horizontal Layout Group、Layout Elementを使用)
1. 空オブジェクトを作って、子オブジェクトにButtonを何個か追加
2. 空オブジェクトにAdd Component>Layout>Horizontal Layout Groupを追加
3. Horizontal Layout GroupのSpacingでButton同士の間に余白をつける
4. Horizontal Layout GroupのChild Force ExpandのWidthとHeightのチェックを外す
5. 子オブジェクトのButtonにAdd Component>Layout>Layout Elementを追加
6. Layout ElementのPreferred WidthとPreferred Heightにチェックを入れてサイズを調整
7. 余白を埋めたい場合はFlexible WidthとFlexible Heightも設定

ボタンをグリット状に並べて表示

(Grid Layout Group、Content Size Fitterを使用)
1. 空オブジェクトを作って、子オブジェクトにButtonを何個か追加
2. 空オブジェクトにAdd Component>Layout>Grid Layout Groupを追加
3. 空オブジェクトにAdd Component>Layout>Content Size Fitterを追加
4. Content Size FitterのHorizontal FitとVertical FitをPreferred Sizeに設定
5. 空オブジェクトにAdd Component>UI>Imageを追加
6. Grid Layout GroupのPaddingで上下左右の余白を調整
7. Cell Sizeでボタンの高さと幅を調整
8. Spacingでボタン同士の余白を調整
9. Start Conrnerでどこから並べるか設定して、Start Axisでどちら方向に向かって並べるか設定
10. ConstraintをFixed Column CountかFixed Row Counを設定して、Constraint Countで列か行に表示する数を制限する

その他のメモ

  • スマホのUIを作るのにAutoLayout機能はとても便利(使いこなすまでが難しい)
  • リストビューなどはLayout機能を使えばリストの追加などをスクリプトで制御しやすくなる
  • グリットレイアウトはダッシュボードにしたりカレンダーに使ったり色々できる
  • おもしろいメニューを作ってる記事を見つけた(AutoLayoutではできなそう) http://iwashigame.hatenadiary.jp/entry/2015/09/14/013024

参考になりそうなサイトやAsset

スマホのUIに使えそうな参考サイト
http://www.nxworld.net/inspiration/admin-dashboard-design-showcase-1.html
http://www.slideshare.net/bookslope/hcdnet-sd06-uipatterns2014
http://meglog.net/web-service/gallery-of-smartphone-site.html

自動レイアウトの参考サイト
http://ashlot.net/2015/05/08/unity-ugui-scroll/
http://tsubakit1.hateblo.jp/entry/2015/02/07/235900
http://www.slideshare.net/RyoheiTokimura/unite2015-u-gui
http://albatrus.com/main/unity/7506

今後の課題

スマホなどで解像度が変わった時にレイアウトが正しくなるかは試してない。
横に画面が回転した時にどう対処するか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VRMからVRChatへアップロードする流れ

:warning: 注意事項

  • VRMによっては、ポリゴン数が70000を超えている、VRChatに対応したボーン構造になっていないなどの理由で、この記事の手順ではアップロードが出来ない場合もあります。
  • VRChatは修正不能な脆弱性により、モデルのデータを第三者が盗める状態になっています。もちろんそのような行為は規約により禁止されていますが、モデルデータをアップロードする際はその問題を認識したうえで行ってください。
  • VRChatへのアップロードは、データの転載に当たります。あらかじめデータの権利関係・ライセンスをご確認ください。

Unityエディタのインストール

VRChatへのモデルデータ (以下、アバター) のアップロードは、Unityエディタを使って行うことになっています。Unityエディタのインストールはとても時間がかかるので、とりあえずやって放置しておきましょう。

VRChat用に必要なUnityエディタのバージョンは 2017.4.15f1 固定になっているので、以下のURLからこのバージョンのインストーラーをダウンロードして実行します。1
https://download.unity3d.com/download_unity/5d485b4897a7/UnityDownloadAssistant-2017.4.15f1.exe

このバージョンには脆弱性があるため、以下のページから脆弱性に関連する機能を無効化するツールもダウンロードしておき、Unityのインストール完了後すぐに実行します。
https://unity3d.com/security/mitigation

VRChat側の操作

VRChatのインストール

もしまだVRChatをインストールしていなければ、以下のページにある ゲームをプレイ (緑色の) ボタンを押して、インストールしておきます。

Steam:VRChat
https://store.steampowered.com/app/438100

VRChatのアカウントを作成

VRChatのアカウントには、まぎらわしいですが VRChatアカウントSteamアカウント の2種類があります。

アバターをアップロードするには、 VRChatアカウント をWebページから作成する必要があります。

以下のURLから、VRChatアカウント を作成します。
https://www.vrchat.com/home/register

※ここで入力した「Username」は後から変更することはできないので、注意してください。 Display Name (VRChat内で頭の上に表示される名前) は3ヶ月に1回の制限付きですが、変更可能です。

すでに「Steamアカウント」でVRChatへログインしている場合

Settings画面の右下に UPGRADE ACCOUNT というボタンが表示されていれば、それは「Steamアカウント」です。

  1. VRChatにログインします。
  2. メニューを出します。
  3. 中段の右端にある Settings ボタンを押します。
  4. Settgins画面の右下にある UPGRADE ACCOUNT ボタンを押します。
  5. 開いたダイアログの Generate ボタンを押します。
  6. Copy ボタンを押すと、Generateボタンを押した後に表示された文字の羅列 (トークン) がクリップボードにコピーされます。
  7. https://www.vrchat.com/home/steamlink を開きます。
  8. ENTER MERGE TOKEN と書かれた下のテキスト入力欄に、トークンを貼り付けて、 Merge Accounts ボタンを押します。
  9. VRChatの方は、Settings画面の左下にある LOGOUT ボタンを押して「Steamアカウント」からログアウトします。

アカウントの信用ランクを上げる

VRChatでは、アカウントごとに5段階の Trust Rank (信用ランク) が設定されています。これが Visitor の場合、アバターのアップロードができません。

自分のランクは次の手順で確認できます。

  1. メニューを出します。
  2. 上段の真ん中右にある Social ボタンを押します。
  3. In Room のところに自分がいるので、それをクリックすると、自分のユーザーページが開きます。
  4. 右上の表示名の下に Trust Level: という項目があります。その右の文字列がランクです。

このランクは、VRChatをプレイしていくうちに変わっていきますが、単純にプレイ時間が増えると変わるものではなく、さまざまな条件 (※具体的な内容は非公開) で変わります。

たとえば初心者向けのVRChatツアーのように、いくつかのワールドをめぐるようなツアーに参加し、最初に何人かとフレンドになってもらえれば、ツアーが終わる頃には New User になるでしょう。

VRChat SDKの導入

VRChatへのアバターのアップロードには、Unityエディタを使うと述べましたが、VRChat公式が公開している拡張機能も追加する必要があります。こちらもなかなか時間がかかるので先にやっておきます。

  1. 以下のURLから最新のVRChat SDKを入手します。2
    https://www.vrchat.com/download/sdk
  2. Unityエディタを起動します。
  3. サインイン画面が表示されるので、「Skip」しておきます。
  4. 右上の「+New」をクリックし、「Create project」でプロジェクトを作成します。
  5. ダウンロードしておいたSDKを、下の Assets という領域にドラッグ&ドロップします。
  6. 「Import Unity Package」というダイアログが表示されるので、そのまま右下の「Import」を押して、完了するまで待ちます。

VRMのインポートと変換

UniVRM と VRM Converter for VRChat の導入

Unityのライブラリとエディタ拡張です。『UniVRM』はVRMのインポートに、『VRM Converter for VRChat』はVRChatに適したオブジェクトへの変換に使用します。

  1. 以下のURLから最新版 (右の赤いボタンのうち一番上のものから) を入手します。
    https://pokemori.booth.pm/items/1025226
  2. ダウンロードしたファイルを展開 (解凍) します。
  3. 2つのunitypackageが入っているので、ファイル名に UniVRM という文字が含まれる方を Assets にドラッグ&ドロップし、「Import」します。

VRMのインポート

  1. VRMファイルを Assets へドラッグ&ドロップすると、自動的にインポート処理が行われます。
  2. 処理が完了して操作できるようになるまでしばらく待ちます。
  3. [VRMファイル名].prefab となっているものが、インポート処理で作成されたプレハブです。

VRChat用に変換

  1. Assetsのプレハブを選択した状態で、上の VRM メニューから、 Duplicate and Convert for VRChat を選択します。
  2. 「VRM Converter for VRChat」というダイアログが開くので、右下の 複製して変換 ボタンを押します。
  3. 保存先をたずねるダイアログが開きますが、そのまま 保存 ボタンを押してしばらく待ちます。
  4. 正常に変換が完了すると、「変換が完了しました。」というメッセージを含むダイアログが表示されます。

VRChatへアップロード

VRChat SDKへログイン

  1. 上の VRChat SDK メニューから、 Setting を選択します。
  2. 「VRChat Settings」というウィンドウが開くので、メールアドレスとパスワードを入力して Sign In
  3. 「Avatar Creator Status: Allowed to publish avatars」と表示されているのを確認し、「VRChat Settings」ウィンドウを閉じます。

アップロード

  1. 上の VRChat SDK メニューから、 Show Build Control Panel を選択します。
  2. 「VRChat」ウィンドウが開くので、 Build & Publish をクリックしてしばらく待ちます。
  3. 中央の「Game」ウィンドウにアップロード画面が表示されるので、画面上で指示されている手順に従ってアップロードします。
  4. 正常にアップロードが完了すると、「Upload Comlete! Launch VRChat to see your uploaded content.」というダイアログが表示されます。

  1. このURLは、Unity QA — LTS Releases — Unityから見つけることができます。 

  2. このURLは、VRChatのWebページにログイン後、メニューの「Download」から見つけることができます。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity ステージセレクトなどで文字を大きくする方法

はじめに

この記事で行うこと
・実行中にUIの文字の大きさを変える
・配列を使って選んでいるステージを管理する

準備

・Hierarchyで [Create → UI → Text]でTextUIを2つ作る
・Projectで [Create → C#Script]でScriptを1つ作る
キャプチャ.JPG

Scriptを書こう

①フィールドに
int型のstageNumber(選択しているステージを判別する用)
Text型のtext1,text2(大きくしたい文字)

public Text text1;
public Text text2;
private int stageNumber;//ステージ番号は変換されると困るのでprivateだよ!

②StartメソッドでstageNumberを初期化しよう

void Start()
{
   stageNumber = 0;//最初に選択されているステージは1なのでここで設定しているよ
}

③Updateメソッドにコードを書こう
左右キーを押したときに選択しているステージの値を増やしたり減らしたりする
ステージの値によって対応した文字を大きく表示する

void Update()
    {
        //右のキーを押したとき、ステージ番号が1以下ならステージ番号を+1する
        if (Input.GetKeyDown(KeyCode.RightArrow) && stageNumber < 1)
        {
            stageNumber++;
        }
        //左キーを押したらとき、番号が0以上ならステージ番号を-1する
        if (Input.GetKeyDown(KeyCode.LeftArrow) && stageNumber > 0)
        {
            stageNumber--;
        }

        //選択しているステージの文字を大きく表示
        if (stageNumber == 1)
        {
            text1.fontSize = 30;
            text2.fontSize = 50;
        }
        else
        {
            text1.fontSize = 50;
            text2.fontSize = 30;
        }

    }

④オブジェクトをアタッチして完成!
スクリプトはGameObjectを作って入れるとGood!
キャプチャ2.JPG

左右キーを押せば文字が大きくなるよ!
キャプチャ1.JPG

終わりに

今回は文字を大きくすることだけをやりましたが、こういった感じに文字を大きくするだけでも見栄えが変わるのでオススメです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】Cloud Diagnostics と NCMBが競合してAndroidでビルドエラー Program type already present: com.nifty.cloud.mb.ncmbgcmplugin.GCMInit$1

Cloud Diagnosticsとは

cloud-diagnostics
Setting up Cloud Diagnostics

エラー

CommandInvokationFailure: Gradle build failed. 
/Applications/Unity/Hub/Editor/2018.4.0f1/PlaybackEngines/AndroidPlayer/Tools/OpenJDK/MacOS/bin/java -classpath "/Applications/Unity/Hub/Editor/2018.4.0f1/PlaybackEngines/AndroidPlayer/Tools/gradle/lib/gradle-launcher-4.6.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
stderr[
D8: Program type already present: com.nifty.cloud.mb.ncmbgcmplugin.GCMInit$1
FAILURE: Build failed with an exception.

(以下割愛)

Cloud Diagnosticsをインストールしてビルドしてみるとエラー。
非常に長いエラーメッセージが表示されますが、よく見るとncmbgcmpluginに含まれるGCMInit$1が重複してますよーって書いてある。

環境

MacOSX 10.14.5
Unity 2018.4.0f1
NCMB Version 2.0
Unity User Reporting 0.2.4-preview

解決方法

NcmbGcmPlugin.aarに含まれるclasses.jarに含まれるGCMInit$1.classを取り除きます。

手順

 Finderでプロジェクトを開き、NcmbGcmPlugin.aarを検索する

MyProject/Assets/Plugins/Android/NcmbGcmPlugin.aar

 NcmbGcmPlugin.aarの拡張子を.zipに変えて解凍する

image.png

 classes.jarの拡張子を.zipに変えて解凍する

image.png

classes/com/nifty/cloud/mb/ncmbgcmplugin/GCMInit$1.classを削除

image.png

classes.jarに圧縮する

image.png

image.png

image.png

image.png

image.png

image.png

NcmbGcmPlugin.aarに圧縮する

image.png

image.png

image.png

image.png

image.png

これをやってもエラーになる場合

他にもNcmbGcmPlugin.aarがあるかもしれないと思ってFinderで検索するとTempフォルダ配下にもあります。Tempフォルダは消しても新しく作り直されるので、フォルダごと削除して再度ビルド。
うまくいきました。

image.png

おまけ

Cloud Diagnosticsはよさそう!

Unityダッシュボードでレポートを見れますが、プロジェクトに入れただけなのに過去に遡って見れました。
(あれ?前から見れた?)
すごい、こんな詳しく...
てか、わたしのアプリエラー多すぎ....?!
(あとエディタのエラーも混ざってるっぽい?)

image.png

image.png

エラー詳細
image.png

無料版だと過去7日間しか保持されないため、これはPlusにしたくなりますね。
image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む