需要帮助使用ScriptableObjects列表创建清单系统

时间:2018-12-18 01:49:55

标签: c# unity3d

已解决

感谢您抽出宝贵时间来查看我的问题。

我目前正在使用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的实例,还是必须通过代码填充我的世界?

任何帮助我都会很感激的,已经有一段时间了。

1 个答案:

答案 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的预制件并产生它们可能是最容易的。让我知道您是否还有其他问题。