カーソルが乗っているUIのオブジェクトを取得するでインベントリ内のアイテムの情報を取得できるようになったので、アイテムをインベントリから取り出せるようにしてみました。
まず操作を指示するためのドロップダウンのプレハブを作りました。ドロップダウンでなくても良いかもしれません。
ドロップダウンにスクリプトを付けて、On Value Changedの左下の欄にスクリプトのコンポーネントをドラッグアンドドロップし、そのスクリプトに書いたメソッドを選択します。
メソッドを選ぶ時に同名のメソッドが2つ見つかりますが、引数を入力する欄が無い方を選ぶと、DropdownコンポーネントのValueの値が引数に渡されます。ドロップダウンに並ぶ項目を選択すると、Valueの値がその項目のインデックスになります。項目はOptionsで設定できます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemDropdown : MonoBehaviour
{
Goods goods;
public Goods GetGoods()
{
return goods;
}
// ドロップダウンの値が変わった時に呼ばれる
public void OnValueChanged(int value)
{
switch (value)
{
case 1:
PopItem();
break;
default:
DestroyDropdown();
break;
}
}
public void SetUp(Vector2 position,Goods goods)
{
RectTransform rt = GetComponent<RectTransform>();
rt.position = position;
this.goods = goods;
}
public void PopItem()
{
DisplayMenuOperation.GetInstance().PopItem();
}
public void DestroyDropdown()
{
DisplayMenuOperation.GetInstance().DestroyDropdown();
}
}
このメソッドが呼ばれると、Valueの値によって別のメソッドが呼ばれます。ドロップダウンを作る時にドロップダウンの表示位置を設定して、アイテムクラスのオブジェクトを記憶します。
アイテムを取り出すと、メニュー表示クラスのアイテムを取り出すメソッドが呼ばれます。このクラスでは、アイテムの画像にカーソルが乗っていると、インベントリ内のアイテムの情報を取得して、その時に右クリックするとドロップダウンを作ります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
class DisplayMenuOperation : DisplayMenu
{
static DisplayMenuOperation instance;
public static DisplayMenuOperation GetInstance()
{
return instance;
}
bool opened;
PointerEventData pointer;
[SerializeField] Text text;
bool hasDropdown;
ItemDropdown dropdown;
void Start()
{
instance = this;
pointer = new PointerEventData(EventSystem.current);
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.G))
{
if (GetMenuActiveSelf(0))
{
CloseMenu(0);
opened = false;
DestroyDropdown();
}
else
{
CloseAllCanvas();
OpenMenu(0);
opened = true;
}
}
else if (Input.GetKeyDown(KeyCode.Alpha2))
{
if (GetMenuActiveSelf(1))
{
CloseMenu(1);
opened = false;
}
else
{
CloseAllCanvas();
OpenMenu(1);
opened = true;
}
}
text.text = "";
if (opened)
{
List<RaycastResult> results = new List<RaycastResult>();
pointer.position = Input.mousePosition;
EventSystem.current.RaycastAll(pointer, results);
if (results.Count == 0 && (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1)))
{
opened = false;
DestroyDropdown();
CloseAllCanvas();
ReleasePlayer();
}
foreach (RaycastResult target in results)
{
Goods goods = target.gameObject.GetComponent<Goods>();
if (goods != null)
{
text.text = ItemManager.GetInstance().GetItem(goods.GetItemName()).GetInformation() + " " + goods.GetItemGameObject().name;
// クリック
if(Input.GetMouseButtonDown(1))
{
RightClickImage(Input.mousePosition, goods);
}
}
}
}
}
public void RightClickImage(Vector2 mousePosition, Goods item)
{
if (hasDropdown) return;
hasDropdown = true;
dropdown = Instantiate(dropdownPrefab.gameObject, GetItemCanvas().transform).GetComponent<ItemDropdown>();
dropdown.SetUp(mousePosition, item);
}
// ドロップダウンを削除
public void DestroyDropdown()
{
if (hasDropdown)
{
hasDropdown = false;
Destroy(dropdown.gameObject); // ドロップダウンを消す
}
}
// アイテムを取り出す
public void PopItem()
{
DestroyDropdown();
Destroy(dropdown.GetGoods().gameObject); // アイテムの画像を消す
Inventory.GetInstance().PopGoods(dropdown.GetGoods());
CloseAllCanvas();
ReleasePlayer();
opened = false;
}
}
アイテムを取り出すメソッドが呼ばれると、ドロップダウンを削除して、アイテムの画像を消します。また、インベントリのクラスのアイテムを取り出すメソッドを呼びます。
// インベントリ
public void RemoveGoods(Goods goods)
{
inventory.Remove(goods);
}
public void PopGoods(Goods goods)
{
RemoveGoods(goods);
goods.GetItemGameObject().SetActive(true);
goods.GetItemGameObject().transform.position = Player.Getintance().transform.position + Player.Getintance().transform.forward * 2f;
}
このメソッドでは、インベントリが持つリストからそのアイテムを削除して、アイテムのゲームオブジェクトをアクティブにしてプレイヤーの目の前に移動します。
メニュー表示クラスでは、ドロップダウンが一つしか作られないようにしたり、アイテムを取り出したときにメニューを消してプレイヤーの移動回転等を解放しています。また、画像やドロップダウンの上にカーソルが無い時にマウスをクリックしてもメニューが閉じます。
メニュー表示の基底クラスでは、Canvasの操作とプレイヤーやカーソルのロックの操作を分けてみました。
// DisplayMenu
// ...
// メニューを開く
protected void OpenMenu(int canvasIndex)
{
if (canvasIndex >= canvases.Length || canvasIndex < 0) return;
// Canvasを表示
canvases[canvasIndex].gameObject.SetActive(true);
LockPlayer();
}
// メニューを閉じる
protected void CloseMenu(int canvasIndex)
{
if (canvasIndex >= canvases.Length || canvasIndex < 0) return;
// Canvasを非表示
canvases[canvasIndex].gameObject.SetActive(false);
ReleasePlayer();
}
// ...
public void LockPlayer()
{
playerScript.LockPosition(true); // プレイヤーの位置を固定
cameraScript.LockRotation(true); // 回転を固定
cameraScript.LockCursor(false); // カーソルロックを解除
}
public void ReleasePlayer()
{
playerScript.LockPosition(false); // プレイヤーの移動を自由にする
cameraScript.LockRotation(false); // 回転を自由にする
cameraScript.LockCursor(true); // カーソルをロック
}
これでインベントリ内のアイテム操作ができました。
ドロップダウンのクラスではドロップダウンを選択したときにメニュー表示クラスのどのメソッドを呼ぶかを決めて、メニュー表示クラスでは、ドロップダウンを生成、削除やメニューのオンオフをします。
そして、インベントリのクラスではリストから削除するなどの処理をするようにします。役割をもう少し整理したほうがいいかもしれません。