ブルーノのC#プログラミング & unity勉強日記

プログラミング素人、ブルーノの自主勉強ノートです。他のプログラミングを勉強したい方の助けになれば幸いです。その他趣味の雑記もしていきたいです

Scene '' couldn't be loaded because it has not been added to the build settings or the AssetBundle has not been loaded.の対応

シーンを読み込む際に発生するこのエラー

  • Build SettingからScenes In Buildに入れている
  • 呼び出すシーン名、インデックスは間違っていない

のに発生しているので困っていた

結論から言うと、読み込みたいシーンはScenes In Buildに設定していたが、「読み込みを開始するシーン(SceneManager.LoadSceneを呼び出したシーン)」の方をScenes In Buildに入れていなかったために発生していたらしい。

こちらのシーンも登録したところエラーが解消されシーン遷移できるようになった
全然他記事がなかったのでメモしておく

環境:Unity2020.3.22f1, エディタ上, プラットフォームはiOSに設定

Privacy Policy for Bruno Games

Privacy Policy

Effective date: January 20, 2021

Bruno Games ("us", "we", or "our") operates the Bruno Games mobile application (hereinafter referred to as the "Service").

This page informs you of our policies regarding the collection, use and disclosure of personal data when you use our Service and the choices you have associated with that data.

We use your data to provide and improve the Service. By using the Service, you agree to the collection and use of information in accordance with this policy. Unless otherwise defined in this Privacy Policy, the terms used in this Privacy Policy have the same meanings as in our Terms and Conditions.

Definitions

Service

Service is the Cup Shuffle mobile application operated by Bruno Games

Personal Data
Personal Data means data about a living individual who can be identified from those data (or from those and other information either in our possession or likely to come into our possession).

Information Collection and Use

We collect several different types of information for various purposes to provide and improve our Service to you.

Types of Data Collected

Personal Data
While using our Service, we may ask you to provide us with certain personally identifiable information that can be used to contact or identify you ("Personal Data"). Personally identifiable information may include, but is not limited to:

Use of Data

Cup Shuffle uses the collected data for various purposes:

  • To provide and maintain our Service
  • To notify you about changes to our Service
  • To allow you to participate in interactive features of our Service when you choose to do so
  • To provide customer support
  • To gather analysis or valuable information so that we can improve our Service

Transfer of Data

Your information, including Personal Data, may be transferred to - and maintained on - computers located outside of your state, province, country or other governmental jurisdiction where the data protection laws may differ from those of your jurisdiction.

If you are located outside and choose to provide information to us, please note that we transfer the data, including Personal Data, to and process it there.

Your consent to this Privacy Policy followed by your submission of such information represents your agreement to that transfer.

Bruno Games will take all the steps reasonably necessary to ensure that your data is treated securely and in accordance with this Privacy Policy and no transfer of your Personal Data will take place to an organisation or a country unless there are adequate controls in place including the security of your data and other personal information.

Disclosure of Data

Legal Requirements
Cup Shuffle may disclose your Personal Data in the good faith belief that such action is necessary to:

  • To comply with a legal obligation
  • To protect and defend the rights or property of Cup Shuffle
  • To prevent or investigate possible wrongdoing in connection with the Service
  • To protect the personal safety of users of the Service or the public
  • To protect against legal liability

Security of Data
The security of your data is important to us but remember that no method of transmission over the Internet or method of electronic storage is 100% secure. While we strive to use commercially acceptable means to protect your Personal Data, we cannot guarantee its absolute security.

Service Providers
We may employ third party companies and individuals to facilitate our Service ("Service Providers"), provide the Service on our behalf, perform Service-related services or assist us in analysing how our Service is used. These third parties have access to your Personal Data only to perform these tasks on our behalf and are obligated not to disclose or use it for any other purpose.

Analytics

We may use third-party Service Providers to monitor and analyse the use of our Service.

Google Analytics
Google Analytics is a web analytics service offered by Google that tracks and reports website traffic. Google uses the data collected to track and monitor the use of our Service. This data is shared with other Google services. Google may use the collected data to contextualise and personalise the ads of its own advertising network.

You may opt-out of certain Google Analytics features through your mobile device settings, such as your device advertising settings or by following the instructions provided by Google in their Privacy Policy: https://policies.google.com/privacy

For more information on the privacy practices of Google, please visit the Google Privacy & Terms web page: https://policies.google.com/privacy

Unity Analytics
Unity Analytics is provided by Unity Technologies.

For more information on what type of information Unity Analytics collects, please visit their Privacy Policy page: https://unity3d.com/legal/privacy-policy

Links to Other Sites

Our Service may contain links to other sites that are not operated by us. If you click a third party link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit. We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services.

Children's Privacy

Our Service does not address anyone under the age of 18 ("Children").

We do not knowingly collect personally identifiable information from anyone under the age of 18. If you are a parent or guardian and you are aware that your Child has provided us with Personal Data, please contact us. If we become aware that we have collected Personal Data from children without verification of parental consent, we take steps to remove that information from our servers.

Changes to This Privacy Policy

We may update our Privacy Policy from time to time. We will not notify you of any changes by posting the new Privacy Policy on this page. Prominent notice on our Service, prior to the change becoming effective and update the "effective date" at the top of this Privacy Policy.

You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page.

Contact Us
If you have any questions about this Privacy Policy, please contact us: covory5239@gmail.com

【Unity】Finger IdとInput.touchesのインデックスの関係

f:id:covory10101101276:20200516101433j:plain
イエローナイフ -カナダ-

みなさんこんにちは🌑

相変わらず外出自粛の防災無線が毎日家のすぐそばで鳴り響いているブルーノです。主要都市部以外は緊急事態宣言が解除されましたね。いいなあ。あまりにも外が恋しくて最近は十何時間ある自然の動画をYoutubeで流しながら生活しています。


さて、今回も私がアプリを作るうえで少しだけ引っ掛かった、タッチの参照について調べたことをまとめていきます。


今回のケース

とあるスマホアプリの開発において、画面半分のタッチは移動に割り当てられ、画面もう半分はカメラの移動に充てられるといった、よくあるスマホ版TPSアプリのような操作を実装することになりました。
f:id:covory10101101276:20200516102835j:plain
タッチが検知されたら押されている間その指の情報を常に取得するクラスを移動用とカメラ操作用で二つ作り、タッチの動向を見守ろうとしました。Unityの仕様では、タッチはInput.Touchクラスで管理されています。
docs.unity3d.com

またそれらを配列として所有するInput.touchesもあります。
docs.unity3d.com
こちらの"touches"は小文字。

というわけで、このInput.touchesにアクセスし指の状態を取得しようと思ったのですが、実は同じ指の情報が常にInput.touchesの同じインデックスに格納されているわけではないんです。
というのも考えてみれば当たり前で、例えばまず画面に一本指をタッチします。
f:id:covory10101101276:20200516104530p:plain
このタッチ情報はInput.touchesの0番目に格納されます。
次にもう一本画面に指をタッチすると
f:id:covory10101101276:20200516104818p:plain
Input.touchesの1番目に格納されます。ではここで0番目の指が離されるとどうなるか、
f:id:covory10101101276:20200516105208p:plain
Input.touches[1]にあった指の情報が詰められて、Input.touches[0]になります。

さてこれではゲームの実装は少し困ったことになりますね。タッチされた指の配列がいちいち変わるんじゃ、手動で今押されている指はほかの指が離されてインデックス詰められて...といちいち計算させていたんじゃ大変です。
そこでInput.Touchクラスには、fingerIdという変数が備わっています。
docs.unity3d.com
Touchのインデックスがころころ変わるのに対し、このfingerIdは指が離されるまでは変わりません。これを参照し続ければ、ある指の動向をずっと見守ることができます。

とまあタッチ処理についてはここまで知っておけばあまり困ることはないんですが、少し気になったのはこの後のタッチの処理についてです。
先ほどの指の流れにfingerIdも添えて表示するとこうなります
f:id:covory10101101276:20200516110205p:plainf:id:covory10101101276:20200516110216p:plainf:id:covory10101101276:20200516110228p:plain

この状態で指をまたもう一本タッチすると、現在Input.touches[0]の指のインデックスはどうなるか、配列が普通に増えるだけなんだから、こうなるのかと私は思っていました。
f:id:covory10101101276:20200516110544p:plain
しかし、これは間違い。

実際にはこうでした。
f:id:covory10101101276:20200516110915p:plain
右のタッチのインデックスが新しくタッチされたTouchのインデックスの後ろに回ったのです。最初の一連からすると新しくタッチされた情報は常に追加される形で増えそうなものですが、これを見る限り単純にそういうわけではないようですね。
fingerIdに合わせて配列が整理されるのかな?

微妙な内容ですが自分の考えとずれがあったのでまとめておきました。
また、fingerIdもリファレンスに「ユニークなId」と強調して書いてあったからそれぞれ変な数が入っているのかとも思いましたが、案外普通だったのが個人的に一つ収穫です。


今回はここまでにしておきます。

【Unity】Physics.Raycastの引数"LayerMask"の注意

f:id:covory10101101276:20200507192306j:plain
ベルギー -ブリュッセル-

みなさんこんにちは🌞


マイナンバーカードで10万円給付申請をしようと思ったのにいつの間にかカードを無くしていて激込みの役所にまた行かなくてはならなくなってしまったブルーノです。めんどくさいけどいかなきゃ。。。


さて、今回はRayを使った様々なオブジェクトの探索についてこんがらがったので、まとめました。

Rayを使ってオブジェクトを探索するとき、Physics.Raycast()もしくはPhysics2D.Raycast()を使いますよね。
docs.unity3d.com
docs.unity3d.com

しかし間に余計なコライダーがいくつもあってRayが遮られてしまい、取得したいオブジェクトにRayがあたらない!なんてことありませんか?
そんな時は例えば以下のような対処法が挙げられます。

1. Physics.RaycastAll(Physics2D.RaycastAll())を使う

docs.unity3d.com
docs.unity3d.com

Raycastの結果を受け取る配列を用意し、そのすべてをforeach文で検証していきます。3Dと2Dで受け取り方が微妙に違うので注意。ただしforeach文での探索はコストがかかるので毎フレーム行う場合にはお勧めしません。

2. collider.RayCast()を使う

docs.unity3d.com
飛ばしたRayのうち、「このコライダーだけを探せ!」というような処理をすることができます。最初から探したいオブジェクトが決まっていればこちらを使うと早いです。1. よりもコストはかかりませんが、探したいオブジェクトが決まっていない場合には少々使いずらいです。

というわけで、今回は後述する3. の方法がメインの話となります。


3. LayerMaskを指定してオブジェクトを探索する。

実は最初に挙げたPhysics.Raycast(Physics2D.Raycast)には引数がいくつかあり、その中に引数でLayerMaskを設定できます。これは、入力したint値のレイヤーマスクのみを判別するというものです。
これは便利!!ということで試してみます。
f:id:covory10101101276:20200507200718p:plain
Layer 8に「sphere」を設定
f:id:covory10101101276:20200507200818p:plain
sphereにレイヤーを設定
f:id:covory10101101276:20200507200933p:plain
コードはこんな感じ。21行目のPhysics.raycastの第五引数にレイヤー番号8を入れる。

が、
f:id:covory10101101276:20200507200910p:plain
いくら押しても反応しない。。。。
レイヤー番号は0からだけど引数指定するときは1からなのか?とかバカなこと考えて数字を前後させてみたがダメ。IgnoreRaycastレイヤーは無視されるらしいからそれを抜いた番号なのか?とかアホなこと考えてさらに前後にずらしてみたが反応なし。。。

なぜだ。。。
しばらくネットで情報を探すと(というか一周してリファレンスを見返すと)
f:id:covory10101101276:20200507201954p:plain
DefaultRaycastLayersってなんだ? 普通に考えたら0か...?

docs.unity3d.com
3Dの方は特に目を引く記述はなかったが、
docs.unity3d.com
「マスクの値は IgnoreRaycastLayer マスクのビット補間に相当します。」
2Dの方に気になる記述を発見。ビット補間..?


どうやら、このLayerMaskの値は2bit値で管理されているようです。なのでこの引数に送るのは我々がよく認識する10進数ではなく、2進数での値のようです。
しかも単純にレイヤー番号を2進数にするわけではありません。例えば今回の場合はレイヤー番号は8なので2進数に直すと1000ですが、これも違うのです。
レイヤー番号はビットフラグという管理のしかたがされているようで、普通の管理番号をビットシフトする必要があります。
シフト演算
もうすでに文系の私は意味不明です。
が、これによると1から0を「8」つ増やした値を10進数に直した値が今回のLayerMaskの値ということになります。
ビットシフトはコーディングする際に簡単な方法があり、
f:id:covory10101101276:20200507204317p:plain
21行目にあるように 「1 << レイヤー番号」で求めることができます。


これで試すと....
f:id:covory10101101276:20200507204503p:plain
できました!長かった。。。。



こんなのわかんねーよー。しかもその説明にリファレンスからたどれないし。。。
なんとか仕組みが分かったーでも面倒だなーみんなこんなこと入力してんのか...ん?
docs.unity3d.com
f:id:covory10101101276:20200507205054p:plain
f:id:covory10101101276:20200507205003p:plain



f:id:covory10101101276:20200507205301j:plain




今回はここまでにしておきます。。。

【Unity】インスペクターの変数に初めから値を入れておく方法【Reset()】と地味注意

f:id:covory10101101276:20200507000307j:plain
日本 山梨県-忠霊塔-

みなさんこんにちは🌞

久々に帰ってきたブルーノです。世間でコロナが流行って初のゴールデンウィークですがみなさんいかがお過ごしでしたでしょうか。私は友人とArkのPS4版をやって楽しんでいました。いろいろやりづらさが目立つゲームですが近年のサバイバルゲーの中では破格のグラフィックとクオリティだと思います。



さて、Unityの使い方に少し慣れてくると、[Seriarize Field]などでprivate修飾子をつけた変数をUnityエディタ上から指定する機会等が増えてくると思いますが、その値がわかりきっているのにいちいち手動で設定するのは面倒ですよね。そこで、UnityにはReset()という関数が用意されています。

docs.unity3d.com

公式リファレンスを見ればもうこちらから説明することはないほどわかりやすい機能と説明なんですが、インスペクターの変数に対して自動でReset()内の処理を行ってくれます。

f:id:covory10101101276:20200507002750p:plainf:id:covory10101101276:20200507002802p:plain
こんな感じ

値の初期化などに使えますね。しかし、少しだけこの関数を使うときに注意することがあったのでメモします。

1. インスペクターに表示されていない場合は処理が通らない

Reset()の中に記述した内容はあくまで変数がインスペクターに表示されている場合のみに行われるようです。
具体的にどういうことかというと、
f:id:covory10101101276:20200507003120p:plain
↑のように変数(Sphere)がprivateだと...

f:id:covory10101101276:20200507003035p:plain
初期化されてないのです。

Resetの中身は通っているはずなのに処理がされてないというのは不思議な感じですね。

2. いろいろ変数の修飾子をいじるとResetされてないかもしれない

では今度は、先ほどの1. で書いたコードのSphere変数にそのまま[Seriarize Field]を追加してみました。するとどうなるのでしょうか。
f:id:covory10101101276:20200507003930p:plain
f:id:covory10101101276:20200507003957p:plain
Sphere変数に値が入っていませんね。UnityのReset()という処理が入るのは単純にコードを保存したタイミングではないようです。
こういったときは変数右上の歯車のマークからResetを選択すると、再びリセットされます。
f:id:covory10101101276:20200507004502p:plainf:id:covory10101101276:20200507004512p:plain


以上のように、Reset()は初期化した際にインスペクタの値に自動で値を入れてくれる便利?な関数ですが何かと注意点があるようです。
私の場合は勘違いしてどんな記述でも通るのかと思ってAwake()のような使い方をしていたためReset()内に記述していた変数すべてがNullになっていました。まあリファレンスに書いてあることがすべてで私が早とちりしていただけなのですが笑 そんな大ごとでもすごい発見でもないですが備忘録ということで。

今回はここまでにしておきます。

No.002 完成

f:id:covory10101101276:20190716211229j:plain
アウヤンテプイ -ギアナ高地-

みなさんこんにちは🌚

もう7月も半ばなのに一向に晴れる気配がなくて気分もじめっとしてるブルーノです😓洗濯物が乾かない...
さて今回も今まで作っていた作品をやっていきましょう...と言いたいのですが実は最近作品を完成させてしまい、記録を残していませんでした笑 実は諸事情により記録をつけている余裕がありませんでした。なので今回は完成作品のスクショを貼っていきます。

完成品

f:id:covory10101101276:20190716212553p:plain
タイトル
タイトルメニュー。タイトル画面中はカメラが動き回りながら町中を写しています。

f:id:covory10101101276:20190716213714p:plain
ステージその1

f:id:covory10101101276:20190716213645p:plain
ステージその2

残りも公開しようと思ったのですがAppStoreにあげようと思うので今回の紹介はここまでにしておきます。もし気になったらぜひダウンロードしてくださいね。実際にリリースしたら記事でも紹介しようと思います。

No.002 進捗状況16[ゲーム画面のUIの実装]

f:id:covory10101101276:20190517111503j:plain
コルコバード -ブラジル-

みなさんこんにちは🌚

では今回もやっていきましょう!!

これまでゲーム中のオブジェクトやスクリプトなど、ゲーム全体の中枢をなす舞台を主に作ってきました。今回は実際にユーザーが触れるための境界、媒体となるUIを実装していきます。

MobileSingleStickControlの改良
といっても実は以前導入部分だけは触っているんですよね。ただ一番初めに触るべき場所はここじゃないと思ってそのまま放置してしまいました。過去の記事はこちら
dreameaters5239.hatenablog.com
キャラクター移動のスティックは作ってあるので今回はこのCanvasに加速のボタンとライフを実装しようと思います。
加速ボタン(CrossPlatformInput)
以前作った時計っぽいアイコンはデザイン変更しました。

f:id:covory10101101276:20190517194213p:plain
左上の白丸が加速のためのスイッチ。
会話ウィンドウも後ろに写っていますが開始時に消えるので気にしないでください😇
さて、このMobileSingleStickControlもといCrossPlatformInputは仮想ジョイスティックおよびボタンをInputManagerに割り当てたボタンに対応させることができる機能です。
f:id:covory10101101276:20190517195458p:plain
ButtonについているEventTriggerでどのタイミングで動作するかを設定し、ButtonHandlerで作動させるInputManagerのボタンを指定します。今回はTimeQuickerという名前を指定しました。なおこの指定する名前はInputManagerに登録してないと使えないので注意
f:id:covory10101101276:20190517195915p:plainf:id:covory10101101276:20190517195931p:plain
そして名前空間でUnityStandardAssets.CrossPlatformInputを指定して、InputManager.で呼び出しましょう
下のスクリプトを同じくボタンにコンポーネントとしてつけます。
f:id:covory10101101276:20190517200147p:plainf:id:covory10101101276:20190517200206p:plain
4行目でCrossPlatformInputを指定して、InputManagerを使えるようにしています。そしてこの長いスクリプトを要約すると
・内蔵しているChargeTimerをボタンを押している間増やしていく。
・タイマーが基準値を超えている時にボタンを離すと加速する。
このたった2つに落ち着きます笑
さて、このスクリプトをわざわざButtonに作ったのには実は理由があります。知り合いから教えてもらった小技で、画像を円形に表示できる機能を使って円の満ち欠けを使って時計盤っぽく表現しようと思います。
その方法が下の通り。ImageコンポーネントのImage Typeを[Filled]に、Fill MethodをRadial 360にします。
f:id:covory10101101276:20190517204451p:plain
そしてその下のスライダーを左右させると...
f:id:covory10101101276:20190517204716p:plain
画像が円形に満ち欠けする!!
そして先ほどのスクリプトにこのFill Amountにアクセスする記述をします。
f:id:covory10101101276:20190519122642p:plain
ハイライトしてある部分がその部分ですね。36~39行目に書いてある通りImageコンポーネントを取得、さらにそもそも最初にUnityEngine.UIにアクセスできるよう名前空間を指定するのも忘れないように
そしていろいろリデザインした時計でこれを起動すると!!
f:id:covory10101101276:20190519123013p:plain
動かない!
なんででしょう!どうやら原因はいろいろリデザインにあるらしいです...
いろいろImageを重ねたり子にして階層を配置してしまうとその画像に当たり判定が阻まれてしまい正常に動作しないようです。原因を探っているときよく目にしたCanvasコンポーネントをアタッチしてOverride Sortingという機能を使う対処法もなぜかうまく動作しなかったんですよね。
f:id:covory10101101276:20190520142138p:plain
全ての階層の画像にこのコンポーネントをつけて順番を変えられるはずが...?
なのでまた別の方法を見つけました。Graphic RayCasterという方法です。
f:id:covory10101101276:20190520142406p:plain
これはCanvasにアタッチするタイプのコンポーネントで、これをつけているとこの階層のImageすべてにタッチ情報が送られます。しかし、もちろんImageコンポーネントにRayCast Targetがチェックされていない場合は反応しません。これで....
f:id:covory10101101276:20190520142642p:plain
ようやく成功!!!
やっとできました!!長かったですね。。。

ライフUI
では今回はさらにもう一つゲームにはおきまりのライフゲージを今更ですが実装していこうと思います!!
UIに先ほどと同じ要領でImageたちを配置...
f:id:covory10101101276:20190520155845p:plain
彼らはタッチする必要がないので先ほどのような行程はいりません
f:id:covory10101101276:20190520160013p:plainf:id:covory10101101276:20190520160024p:plain
そしてプレイヤーのスクリプトにライフのint値および敵にあたった時の処理を記述する。この時LifePointはPublicにして他からアクセスできるようにしておきましょう。
f:id:covory10101101276:20190520160233p:plain
そしてこちらの新たに作ったLifePointScriptを先ほどのライフのUIにアタッチします。このスクリプト
・プレイヤーのライフにアクセス
・自身のImageコンポーネントにアクセスし、ライフに応じて画像の満ち欠けを3等分
という風になっています。
さあ起動してみると....

f:id:covory10101101276:20190520160549p:plain
ライフが減ってそれに応じた欠け方になった!
うまくいきましたね。イーサンがいないように見えるのはさっきプレイヤースクリプトに足したコルーチンでイーサンの姿を点滅させているからです。今回はここまでにしておきます。
まだ料理でいうと材料揃える段階から進んでいない....