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

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

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

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

Q&A

1回答

166閲覧

プレイヤーがアイテムを使用した時、 アイテム欄からアイテムを消す処理を書きたいです

kontiwa

総合スコア0

C#

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

0グッド

0クリップ

投稿2024/11/04 07:09

実現したいこと

unityの、ビジュアルスタジオでスクリプトを書いています。
プレイヤーがEキーを押してアイテムを使用した時、
アイテム欄からアイテムを消す処理を書きたいです

プレイヤーが拾ったアイテムを、Item型のitemlstの中に追加しています。
リストの中に追加されたアイテムのスプライトが、
アイテム欄(slots[])の中に順番に表示されていきます

アイテム欄は三つしかないので、
itemlstも三つまでしか入らないようにしました。

slots[]は、ヒエラルキーにある3つのアイテム欄に個別に取り付けられた、複数あるSloteスクリプトを
配列の中に入れています。

リストの中からリムーブしたアイテムのスプライトを、
slots[](アイテム欄)から消したいです。

public class InventryUI : MonoBehaviour

public void UpdateUI()
{

slots = WheponSlotPanel.GetComponentsInChildren<Slot>(); for (int i = 0; i < slots.Length; i++) { //もし、拾ったアイテムの数よりもiが小さければ if (i < Inventry.instance.itemList.Count) { slots[i].AddItem(Inventry.instance.itemList[i]); } }

}

Item[] itemlst = Inventry.instance.itemList.ToArray();

for (int k = 0; k < itemlst.Length; k++) { Slot slotsUI= slots[k]; if (Input.GetKeyDown(KeyCode.E)) { Inventry.instance.itemList.RemoveAt(k); slotsUI.ClearItem(slotsInItem); }

public class Slot : MonoBehaviour
{

public void AddItem(Item itemAdd)
{
item = itemAdd;
icon.sprite = itemAdd.itemedateicons;

}

public void ClearItem(Item item)
{
slotsItam = item;
slotsItam = null;

icon.sprite = null;

}

アイテム欄は、三つ並んでおり、拾ったアイテム(リストの中に入っている)を左から順番に表示します
リムーブしたアイテムのインデックスと、同じインデックスのslotes[]のスプライトを非表示
にしようと思いました。

しかし

Inventry.instance.itemList.RemoveAt(k);

の一行から

ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

というエラーが発生しました。

c#です。
どのように修正したら良いのかわかりません。
是非、ご教授お願いします。

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

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

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

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

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

guest

回答1

0

Logを出力するなどして消す処理が複数回実行されているのか確認してみてください。
複数回実行されているとすれば
k=0の時、Inventry.instance.itemListの数=3、itemList.RemoveAt(0);
k=1の時、Inventry.instance.itemListの数=2、itemList.RemoveAt(1);
k=2の時、Inventry.instance.itemListの数=1、itemList.RemoveAt(2);
という風に動作するかと思います。
このように動くとk=2の時にRemoveAtで指定するIndexがitemListの数を超えてしまうためArgumentOutOfRangeExceptionが発生します。

こういったListの削除の場合はループは大きい数字から小さい数字へとループすれば連続して消されても
k=2の時、Inventry.instance.itemListの数=3、itemList.RemoveAt(2);
k=1の時、Inventry.instance.itemListの数=2、itemList.RemoveAt(1);
k=0の時、Inventry.instance.itemListの数=1、itemList.RemoveAt(0);
と動作するのでArgumentOutOfRangeExceptionは発生しません。

ただ1回のUpdateUIの呼び出しで複数回消す処理が走るのは正しいのでしょうか?

投稿2024/11/04 08:47

YAmaGNZ

総合スコア10469

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

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

kontiwa

2024/11/04 10:47 編集

回答ありがとうございます。 参考にし書き換えてみたところArgumentOutOfRangeExceptionのエラーを修正する事ができました。 しかし、指摘して頂いた通り複数回処理が走っているからなのか、例えばslots[2]のスプライトだけを消したいのに、slots[0]やslotes[1]などの全てのアイテムの表示が消えてしまいます。 (リストからは[2]しか消えていません) どのように書き換えれば良いのか、何かアドバイスがあれば教えていただけると幸いです。
YAmaGNZ

2024/11/04 12:06

アイテムを使用するというのはどのような動作を考えているのでしょうか? インベントリを開いて、使用するアイテムを選択しEキーで使用するという動作でしょうか? それともアイテムを拾った順に使用するという動作でしょうか? そういった動作仕様で考え方が異なるかと思います。 どちらにしろループで消すのではなく消したいアイテムのインデックスを求めてそのインデックスの物だけを消すという動作になるかと思います。
kontiwa

2024/11/04 12:27

使用するアイテムを選択し、使用するという動作です。 消したいアイテムのインデックスを求める方法で、再度書き換えて見ようと思います。 初めてアイテム欄のスクリプトを書くので戸惑っていました。 親切に教えて頂き、本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問