Unity ScrollViewをフリックで操作する
タイトル通りです。
フリックを検知する
こちらのサイトさんが参考になりました。
改良した点は、フリックの方向もわかるようにしたこと。といっても、それほどいじったわけではなく、タッチの始まり点と終わり点のx座標の差をとって、方向を調べているだけです。後はそれに準じて、別のメソッドを呼んであげたりすることで、方向もしっかりと検知することができました。何よりしっかりとしたスクリプトを載せていただけていたのですごく勉強になりました。
ScrollViewをフリックで動かす
ScrollViewを使用する必要はないです。僕はScrollVewを作成した後、改良しようとして今に至っているので 使っているだけです。ScrollViewを使用しない場合は、コンポーネントを綺麗に横(縦)に並べて、それをフリックによって左右に移動させてやればOKです。(iTweenが良いよ)
まず、ScrollView固有のスクロール機能を切ってしまいます。ここの2つのチェックw外せばOK
こうすることで、コンポーネントをContentの中に詰めたとしても、それが移動することはありません。
後は、先ほど作成したフリック検知スクリプトより、移動メソッドを読んであげればOK
nowPanelは現在表示中のパネルを記憶し、端のパネルがさらにスクロールしそうになったらreturnする為に使用します。後は、パネル間の距離を算出し、その分だけ全てをiTweenで移動させてやります。これで、フリックに対応したScrollViewができます。
結論を言うと、なんらかの方法でパネルを縦か横に並べ、それをフリック検知により移動させてあげれば、操作できているような感覚になります。
Unity ダメージ表示UIを作る
RPGとかでよくあるやつ!9999みたいな!さて腰を据えて作ろうかなと思って10秒経たずに素晴らしいサイトを見つけてしまった笑 トップに表示されるぐらいだから、おそらく誰もが一度は見たことあるであろうサイトさんですが、、笑
[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく
僕のFF魂をくすぐりました笑 もう参考にさせてもらうしかない!
ベースはありがたく使用させていただくことに
Animationなんてチュートリアルで触って以来です。ただいい機会なので慣れておきたい。サイトさんにはここら辺の設定は割愛されていたので自分なりにとりあえずシンプルに実装して見た。
y座標を少し移動させるだけ!多分、同じことをやっている笑 終了判定のスクリプトはほぼそのまま使用させていただきました。こちらの終了判定は、のちに実装するフェードアウトを、全ての数字が表示し終わったタイミングで実行するために使用されています。
メインのスクリプトの方は若干いじらせてもらいました。具体的には、スクリプトを初めからダメージ管理オブジェクトにつけて置いて、DamagePopUp()メソッドに引数としてダメージとワールドの表示場所を渡して呼び出せば、いつでもダメージのアニメーションが表示されるようにしました。
スクリーン座標の計算
ダメージは当然、受け手付近に表示させなければいけません。参考にさせていただいたサイトさんはこちら。
UnityのCameraが使う3つの座標系 - テラシュールブログ
【Unity】【uGUI】Screenの座標とWorld(3D)座標の変換について - テラシュールブログ
スクリーン座標の取得 凛(kagring)のUE4とUnityとQt勉強中ブログ
結果的には、MainCameraのWorldToScreenPoint()メソッドを使用することで、なんの苦労もなくできてしまいました。この時注意することは、MainCameraぐらいです。普段使用しているcameraオブジェクトのtagをMainCameraにして置いてください。そうすることで、スクリプト上から Camera.main でアクセスできてしまいます。今の所、カメラを複数使用していないので、なんのエラーもなく座標を変換することができました。
、、、先人さんたちに本当に感謝です。
Unity 再生中のAudioSourceのclipを上書きして放置
タイトル通りです。
今までは音が流れればいいや確認できればいいやの流れであまり気にせずやってきましたが、実際にスマートフォンなどで動かす場合、なるべく消費するメモリは少なくしたいと思いました。なので、Awake時にまとめてリソースをとりあえず読み込んでおく実装をやめ、BGMを変更するたびにそれを毎回読み込むことに!(これくらい初めからやっておけよ!)
この時一つ気になったのは、AudioSourceのclipを変更した時、元のclipはどうなっているのか。
実験1
まずは下のようなコードで実験。nowPlayBGMは常に今流れているBGMを指しています。
実行初期
一曲目を再生すると、、
二曲目を再生
もう一度1曲目を再生してもメモリは変わらず。なので、上書きしただけでは消えませんね。
実験2
実は今回再生に使用しているクラスはシングルトンなクラスなのですが、これはモンスターとエンカウントしたらシーンが切り替わる前から戦闘BGMを流し始めたいからです。つまり、一つのBGMは再生されたら次のシーンでもそのまま流れ続けます。では、シーンを遷移させた場合、使われていない方のBGMのリソースは解放されたりはしないのでしょうか?やってみます。
まずこちらが先ほど通り、2曲目を再生させた状態
で、こちらが2曲目を流したまま別のシーンへ遷移した後の状況(2曲目は流れ続けています)
使われていないBGMはしっかりリリースされていますね!さすがUnity!
実験3
無事、使われていないものはリリースされましたが、自分の手で管理するのがやはり一番安全。同じシーン内でもBGMを変更する場面があるかもしれません。なので以下のように書き換えてみました。
まず一曲目を再生した状態
お次は二曲目を再生した状態
しっかりリリースされています!今回の場面では、gameObject.Destory()を使用するとエラーが出てしまいましたが、これを使ってリリースする場面もおそらくあると思います。
まとめ
BGMは一つ一つのデータが大きいから、ボトルネックになりやすいかなと思いとりあえずやって見ました。シーンを跨げば一応解放されますが、自分の手で管理するぶんに越したことはありませんね!
あと、今までコードをブログに直接貼り付けていましたが、今回からgistを使用させてもらいました。バックグラウンドが黒にならないのが気になって、今まで使用していなかったのですが、やはり色付き具合が前より少しマシで、何よりコードとして見やすいかなと思ったので、これからgistを使用することにしました。
以上お疲れです。
雑談 新年迎えたよ
あけおめ!今年は特に頑張らないと行けない年です。しかし、同時にゲームがシュビドゥバと発売される年でもありますね。
ゲーム
まず、任天堂さんのSwitch. 1月中に発表があるらしいですが、今の所の予定だと発売は3月ですね!WiiUの発売も発売日発表から販売開始の期間が短かったようなので、おそらく3月発売は裏切らないのではとは考えています。僕はスプラトゥーンが出たら買います。(発売があまりにも遅ければ躊躇)WiiUは他の需要がなさすぎて、スプラトゥーンだけの理由で買えませんでした笑 なのでこれからのソフトも期待してSwitchは買うと思いますそのうち。
次に、モンハンXX。これはハードを持っているのでソフトは間違いなく買います。ただどこまでやるかなぁと笑 クロスは勲章があと最小金冠のみでその作業中に虚無感に襲われたのでやめちゃいました笑 新作はスタイルの追加ということで、もうフロンティアを超え、モンハンも超えた別ゲームのようになりそうです。一通りやって終わるかもです。
で、新年早々決心したことがあります。FF15買います。うん。やっぱりFFが好きなんですよ。PS3も結局買わないって言って、13-2が出たとたんゲーム屋に走っていき13と同時購入でした笑 LRも買っちゃったし、PS3で後はゲーム買ってないし笑
なのでPS4も買います笑 これからFF7もリメイクされるし(できればリメイクは出ないで欲しかったけど、出るならやる),12もリマスターされるし(12は一番自分に合わなかった)1~9までのまとめパック?の噂も聞いたし。キットPS4は使うので、ためらいなく買ってこようと思います!
なのでSwitchでスプラトゥーンがすぐ出るなら PS4>Switch>モンハンは諦めか少しだけ。スプラトゥーンおとさだなしなら、PS4>モンハン>最悪Switch買わない。という流れ!夢があっていいね!
雑談 Unity〜PlayerPrefsX少し触った
PlayerPrefsXはとても便利ですね。
ArrayPrefs2 - Unify Community Wiki
こちらのリンクから飛ぶことができますが、Gitに乗っているわけではないので、自分でコピペしてスクリプトを作成してください。
boolean配列を適当な順番で値を変更し、その度にその状況を保存しようとしました。この時、PlayerPrefsXさんのSetBoolArrayを使用したのですが、これだと値を書き換える度にすべての値を読み込み、書き込みしなければなりません。まぁ当然、PlayerPrefsで行なっていたらものすごい処理になってしまうのでXさんをしようさせていただいているのですが。。。
ただ結局コーディングしている側からするとやっていることは相変わらず効率悪く感じてしまって。できればまとめて保存したものを、後から部分ごとに変更できたらなぁと思いました。それ最初は負荷かけてPlayerPrefsでちまちま保存して、後で楽すれば、、あれ?じゃあXさんはどうやっているのさ笑
PlayerPrefsXさんの中身見てきました。
public static bool SetBoolArray (String key, bool[] boolArray) { // Make a byte array that's a multiple of 8 in length, plus 5 bytes to store the number of entries as an int32 (+ identifier) // We have to store the number of entries, since the boolArray length might not be a multiple of 8, so there could be some padded zeroes var bytes = new byte[(boolArray.Length + 7)/8 + 5]; bytes[0] = System.Convert.ToByte (ArrayType.Bool); // Identifier var bits = new BitArray(boolArray); bits.CopyTo (bytes, 5); Initialize(); ConvertInt32ToBytes (boolArray.Length, bytes); // The number of entries in the boolArray goes in the first 4 bytes return SaveBytes (key, bytes); } //------------------ enum ArrayType {Float, Int32, Bool, String, Vector2, Vector3, Quaternion, Color}
えっと、英語でも説明してくれてます。。簡単に見ると、
・bool配列をbitにしてbitsに保持、それをbytesにコピー、bytes型に変換してSaveBytes()メソッドに渡してます。
・bytesの先頭にはbool型ということを記憶させています。スクリプトを見るとわかると思いますが、保存したboolを読み込み際に、boolかどうか確認作業がこれを用いて行われています。
・CopyToメソッドは指定先と指定先から見たインデックス番号を渡すと、その場所へ情報をコピーすることが可能なため、32bit分のboolフラグを先頭にしてbool情報をコピーしていることになります。
・Convertint32ToBytesはごめんなさいわからないです
SaveBytes()メソッドは以下のようになっています。
private static bool SaveBytes (String key, byte[] bytes) { try { PlayerPrefs.SetString (key, System.Convert.ToBase64String (bytes)); } catch { return false; } return true; }
チンケな頭を回転させてわかったことは、boolをそのまま配列で保存していたわけではなく、一度byteに変換しそれをstringにさらに変換してPlayerPrefsで保存をしていたということ!
そりゃ、PlayerPrefsをbool配列文回していたら頭悪いですもんね。素晴らしいスクリプトだと思います。しかし完全に流れを抑えられらわけでもなく、stringでまとめて保存しているため、当初の目的であった一部を変更して保存するという戦略は難しそうですね。保存場所からbit数を計算して、stringをbyteに変換し直し、そこの計算して出した部分だけを書き換え、再びstring型で保存すれば理論上は行けそうですが。。少し僕には厳しい!!
ただ今回も細かいところを見学させていただいた結果、bit系の操作は結構頻繁に行われているんだなと実感しました。これから周りの環境を自分通りに作って行く場合には必要な知識なんですよね!頑張ります。
P.S.
年末年始は風邪で寝込んでいたのでテレビ及び電子機器はほとんど触れませんでした。辛い。。けどモヤさまは見たよ!