已解决
感谢您抽出宝贵时间来查看我的问题。
我目前正在使用Unity3D进行项目,在创建清单系统时遇到了一些困难。经过研究后,我决定使用ScriptableObjects(项)列表来创建此清单系统是我的最大利益,因为它易于管理且列表的可扩展性。
仅作为示例,我有一个标题为“头骨”的物品。当玩家指向头骨时,我的代码会提示用户按F键以拾取物品,这又应从游戏世界中移除该物品实例,并将该物品的实例添加到清单中。
给我带来最大麻烦的部分是我的InventoryEditor脚本,该脚本控制了我之前提到的RayCast功能。
这是我的InventoryEditor脚本中的代码,但Update和Start方法无法正常运行
using UnityEngine;
public class InventoryEditor : MonoBehaviour
{
private bool isOpen = false;
public TMPro.TMP_Text itemIDTM;
public GameObject currentObject;
public GameObject inventoryUI;
new Inventory playerInventory;
public void CurrentObject()
{
RaycastHit itemHit;
Ray itemFinder = new Ray(this.transform.position, transform.TransformDirection(Vector3.forward));
if (Physics.Raycast(itemFinder, out itemHit))
{
if (itemHit.collider.tag == "Item")
{
// Rather than itemHit.collider.name I would prefer if it uses the Identifier of the
//Item ScriptableObject V
itemIDTM.text = "F - Pick up: " + itemHit.collider.name;
if (Input.GetKeyDown(KeyCode.F))
{
/*
I need to Add an Item When F is pressed
Something along the lines of:
playerInventory.AddItem(Item that is hit by RayCast);
*/
}
}
else
{
itemIDTM.text = "";
}
}
}
}
这是我的ScriptableObject,没有引起任何问题
using UnityEngine;
[CreateAssetMenu]
public class Item : ScriptableObject
{
public string identifier;
public GameObject model;
public int value;
public double weight;
Item(string identifierStr)
{
this.identifier = identifierStr;
}
}
这是我的广告资源分类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Inventory : List<Item>
{
public List<Item> itemList = new List<Item>();
// Default Constructor
Inventory()
{
}
public override string ToString()
{
string itemListString = " ";
for(int i = 0; i < itemList.Count; i++)
{
itemListString = itemListString += itemList[i].name;
}
return itemListString;
}
public void AddItem(Item itemToAdd)
{
for (int i = 0; i < itemList.Count + 1; i++)
{
if (itemList[i] == null)
{
itemList[i] = itemToAdd;
}
}
}
// Remove Item Not Finished
public void RemoveItem(Item itemToRemove)
{
for (int i = 0; i < itemList.Count; i++)
{
if (itemList[i] == itemToRemove)
{
itemList.Remove(itemToRemove);
}
}
}
}
我能想到的唯一解决方案是使用ScriptableObject.CreateInstance用我希望添加到清单中的物品填充游戏世界,但即使如此,我仍不确定如何两者同时使用:在代码中引用这些物品实例并且,使用RayCast确定正在击中项目实例。是否可以在不使用代码的情况下统一创建ScriptableObject的实例,还是必须通过代码填充我的世界?
任何帮助我都会很感激的,已经有一段时间了。
答案 0 :(得分:0)
因此,与大多数事情一样,有很多方法可以给猫皮剥皮。如果您觉得这需要太多时间,可以使用资产商店中一些出色而复杂的库存系统。如果是我来设置此结构,则我将为您创建一个名为“ IInteractable”的界面,供您希望播放器能够拾取的物品。该界面看起来像这样
public interface IInteractable
{
//once a player has reference to this object they call this
//method to get an item back (which is your scriptable object)
Item GetItemInfo();
}
因此,在您的OnCollision方法中,您不必检查标签,而可以检查像这样的接口。
IInteractable item = itemhit.collider.gameobject.GetComponent<IInteractable>();
if (item != null)
{
//Then you have found an item that needs to be picked up.
string name = item.GetItemInfo().identifier;
}
从这里开始,有几种方法可供您选择,具体取决于您希望库存对角色的影响。对于某些库存,您希望物品立即生效,而对于另一些库存,您希望该物品仅在装备时才起作用。就产生这些物品而言,仅制作带有SO的预制件并产生它们可能是最容易的。让我知道您是否还有其他问题。