Нужна помощь в создании системы инвентаризации с использованием списка объектов ScriptableObjects - PullRequest
0 голосов
/ 18 декабря 2018

решено

спасибо, что нашли время посмотреть мой вопрос.

В настоящее время я работаю над проектом, использующим Unity3D, и столкнулся с некоторыми трудностями при создании системы инвентаризации.Проведя некоторые исследования, я решил, что в моих интересах использовать List of ScriptableObjects (Item) для создания этой системы инвентаризации из-за простоты управления и расширяемости списков.

JustВ качестве примера у меня есть пункт под названием «Череп».Когда игрок указывает на череп, мой код предлагает пользователю нажать 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 голосов
/ 18 декабря 2018

Так что, как и у большинства вещей, есть много способов снять шкуру с кошки.В магазине активов есть несколько блестящих и сложных систем инвентаризации, которые вы можете использовать, если считаете, что это занимает слишком много времени.Если бы я настраивал эту структуру, я бы создал интерфейс, называемый «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 и порождать их.Дайте мне знать, если у вас есть другие вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...