質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

2672閲覧

オブジェクトの画像張り替えスクリプトについて

Dawei

総合スコア10

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2016/10/11 01:57

###前提・実現したいこと
メインカメラにアタッチするスクリプトで、ボタンを押したらx座標が更新されてx座標が300を超えたら0に戻り、0に戻った時に対象のオブジェクト(今回は球体)の画像を張り替えるスクリプトを組もうと思っているのですが、とりあえずで組んだswitch文すら動かなくて困っています。↓の二つのエラーを検索してみてもいまいちよくわからず…
それと張り替える画像が数百枚単位になってしまうためいちいちcase1、case2と書いていくのはかなり手間がかかりそうなのですが何かいい方法はないでしょうか?

参考にしたサイトです
http://qiita.com/ntkgcj/items/61faa07e5a24c59fa950
###発生している問題・エラーメッセージ

FindGameObjectsWithTag can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function. UnityEngine.GameObject:FindGameObjectsWithTag(String) mvcam:.ctor() ArgumentException: FindGameObjectsWithTag can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function. mvcam..ctor ()

###該当のソースコード

using UnityEngine; using System.Collections; public class mvcam : MonoBehaviour { public Vector3 pos = new Vector3(-11, 0, 0); const string BASE_TEXTURE = "Textures/gazou"; //テクスチャを貼りたいゲームオブジェクトの配列生成(タグ名は「SphereObject」) GameObject[] spriteObjects = GameObject.FindGameObjectsWithTag("SphereObject"); //スプライト画像の配列生成(テクスチャ画像の読み込み) Sprite[] sprites = Resources.LoadAll<Sprite>(BASE_TEXTURE); // Use this for initialization void Start() { pos = transform.position; //位置保持 } void Update() { if (Input.GetKeyDown(KeyCode.Space) && pos.x < 300) { //spaceキーの入力があり、かつx座標が300以下の場合にという条件文 pos.x += 30; //x座標を+30する(移動する) transform.position = pos; //位置更新 print(transform.position.x); //コンソールを開くと座標が今どこにいるのかわかるのか書いてくれる } else if (Input.GetKeyDown(KeyCode.Space) && pos.x >= 300) { pos.x = 0; transform.position = pos; print(transform.position.x); foreach (GameObject sp in spriteObjects) { //ゲームオブジェクトのスプライトレンダラ設定を取得 SpriteRenderer spObRender = sp.GetComponent<SpriteRenderer>(); //別スクリプトの変数を取得 //(スクリプト名は「SpriteObjectNumber」、変数名は「spObNum」) int textureUniqueNumber = sp.GetComponent<SpriteObjectNumber>().spObNum; //switch文で、textureUniqueNumber の数字によって処理(貼るテクスチャ)を変える switch (textureUniqueNumber) { case 1: spObRender.sprite = sprites[0]; break; case 2: spObRender.sprite = sprites[1]; break; } } } } } 張り替える対象オブジェクトに付けるスクリプト↓ using UnityEngine; using System.Collections; public class SpriteObjectNumber : MonoBehaviour { public int spObNum; public void Start() { } }

###補足情報(言語/FW/ツール等のバージョンなど)
C#です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Switch文の簡略化の方は、見た限り連番っぽい?ので

C#

1spObRender.sprite = sprites[textureUniqueNumber-1];

とかにすればいけるのではないでしょうか?

後、
GameObject[] spriteObjects = GameObject.FindGameObjectsWithTag("SphereObject");
Sprite[] sprites = Resources.LoadAll<Sprite>(BASE_TEXTURE);
これらはできません。初期化はStart関数の中に移してください。
(プログラムを実際に動かすまで結果がわからない処理はメンバ変数の初期化には使えない)

C#

1GameObject[] spriteObjects; 2Sprite[] sprites; 3void Start() 4{ 5 spriteObjects = GameObject.FindGameObjectsWithTag("SphereObject"); 6 sprites = Resources.LoadAll<Sprite>(BASE_TEXTURE); 7}

投稿2016/10/11 02:58

編集2016/10/11 03:23
ishi9

総合スコア1294

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Dawei

2016/10/11 03:42

ご指摘のところを直してみたのですが、エラーこそ出ないものの画像が切り替わりませんでした。 画像ファイルの名前がgazou(1)、gazou(2)ってふうに着けてるんですが、もしかして違うのでしょうか?
ishi9

2016/10/11 03:51

画像は切り替わらないだけでちゃんと出てはいるんですよね? まずはログを仕込んでいろいろ確認してみるとよいです。 手始めに「textureUniqueNumber」がちゃんと思っている値になっているか確認してみてください。 Debug.Log( "textureUniqueNumber: " + textureUniqueNumber.ToString() ); これを前のコードで言うとSwitchの手前くらいあたりに埋め込んでみてください。
Dawei

2016/10/11 04:01

やってみた結果 textureUniqueNumber: 0 UnityEngine.Debug:Log(Object) mvcam:Update() (at Assets/Script/mvcam.cs:48) と出ました。2回目に0に戻った時もtextureUniqueNumber:0だったので出来ていない?ということでしょうか。 それと画像は最初から貼り付けていたものから変わらなかったです。
ishi9

2016/10/11 04:07

textureUniqueNumberが0の場合があるのでしょうか? それだと私の方で提示した spObRender.sprite = sprites[textureUniqueNumber-1]; はバグるのでif文で0の場合は処理しない等入れておいてください。 それで本題ですが、すいません、よくわからなかったのですが textureUniqueNumberは0以外の値にもちゃんとなっている(動的に切り替わっている)のでしょうか?ずっと0のままなら当然画像は変わらないと思います。
Dawei

2016/10/11 04:16

スクリプトを作動させたときに切り替わっているかということでしょうか。 でしたら0以外の数値にはなっていませんでした。
ishi9

2016/10/11 04:24 編集

となると、画像が切り替わらないのはtextureUniqueNumberが更新されてないのが原因のうちの一つと見て間違いないようです。 textureUniqueNumberの元を辿るとspObNumになりますが、 これに値がちゃんと設定できているか確認する必要があります。 そもそもどうやって設定しているのでしょうか? インスペクタを使っている場合は SpriteObjectNumberのStart関数内に上記と同じ要領でspObNumをデバッグ出力して値がちゃんと入っているか確認してみてください。
Dawei

2016/10/11 04:48

値の設定をしていなかったので0と出たようです。 インスペクタのほうから直接1と入れたところ上記の要領でデバック出力して spObNum: 1 UnityEngine.Debug:Log(Object) とでました。textureUniqueNumberのほうも textureUniqueNumber: 1 UnityEngine.Debug:Log(Object) ですがその後、 IndexOutOfRangeException: Array index is out of range. mvcam.Update () (at Assets/Script/mvcam.cs:54) とエラーが出て、画像が変わらずに止まりました。 それと実はまだSwitch文のほうは変えていなかったのですが、書き方は case 1: spObRender.sprite = sprites[textureUniqueNumber-1]; break; だけでよろしいのでしょうか。
ishi9

2016/10/11 05:16 編集

提示されたコードは0の時の処理がないため、0なら何もしないということで上手く動作していたのでしょう。1を入れてエラーになるということは spritesの中身が空ということです。 これはResources.LoadAllが正しく動作していないからでしょう。 そもそも、Resourcesフォルダにちゃんと素材を置いているかも気になるところです。 「Unityのプロジェクト以下/・・・/Resources/Textures/gazou」 という感じでTextures/gazouの上のフォルダがResourceになっていますか? で、もう一つ、すいません、私の知識不足でした。 spObRender.sprite = sprites[textureUniqueNumber-1]; これは多分思うとおりに動かせません。 なぜなら、Resources.LoadAllがどういう順番で画像を格納しているかわからないからです。ほしい画像を取得したい場合はそのスプライト名を指定する必要があります。 以下のURLを参考にしてください。(まずはその前にspritesの中が空の問題を解決するのが先ですが) http://bribser.co.jp/blog/post-611/
Dawei

2016/10/11 06:10

画像ファイルはとりあえず二つだけ入れてみているんですが(gazou(1),gazou(2)の二つ) Assets/Resources/Textures/gazou(1)といった感じです。
ishi9

2016/10/11 06:15

それでは意図した動作にはならないですね。 Resources.LoadAllに指定するのはフォルダです。 "Textures/gazou"と指定する場合はTextureフォルダの中にgazouフォルダを作成して その中にファイルを入れてください。 なので、以下のようになります Assets/Resources/Textures/gazou/gazou(1)
Dawei

2016/10/11 06:46

上記のフォルダを作成してファイルを入れてから試してみましたが、変わらず IndexOutOfRangeException: Array index is out of range. mvcam.Update () (at Assets/Script/mvcam.cs:54) と出ました。 エラーの出た個所は spObRender.sprite = sprites[0]; です。
Dawei

2016/10/11 07:00

Texture TypeがTextureになってますね。 これを画像のようにSprite (2D and UI)に変更すればいいということですかね。
ishi9

2016/10/11 07:02

ですです
Dawei

2016/10/11 07:06

今度は別のエラーが出ました… MissingComponentException: There is no 'SpriteRenderer' attached to the "Sphere100" game object, but a script is trying to access it. You probably need to add a SpriteRenderer to the game object "Sphere100". Or your script needs to check if the component is attached before using it. UnityEngine.SpriteRenderer.set_sprite (UnityEngine.Sprite value) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/SpritesBindings.gen.cs:238) mvcam.Update () (at Assets/Script/mvcam.cs:54) 該当箇所は spObRender.sprite = sprites[0]; です。
ishi9

2016/10/11 07:27

SphereObjectのTagが付いたコンポーネントの設定がどうなっているかわからないので、ちょっとアドバイスしにくいです。 当初とは大分問題の内容も変わってきたので、ここいらで一旦打ち切って新しく質問を投げるとよいと思います。 その際はSphereObjectのTagが付いたコンポーネントの設定(インスペクタの画面)を画像として添付すると良い回答が得られると思います。(見つけたら私の方も回答してみます)
Dawei

2016/10/11 07:30

わかりました。いろいろ付き合っていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問