gpt4 book ai didi

Inventory System Issue: [The items are not correctly placed in the inventory. ] - [Unity- C#](库存系统问题:[物料未正确放置在库存中。]-[Unity-C#])

转载 作者:bug小助手 更新时间:2023-10-24 22:44:47 28 4
gpt4 key购买 nike



I'm trying to create an inventory system. I have three scripts: Player, GroundItem, and ItemObject. The Player script adds objects I collide with to the inventory. The GroundItem script is attached to the objects in the game world, and the ItemObject scriptable object holds the properties of the item. The issue I'm facing is that when I collect a fourth item, even if it's stackable, it places it in a different slot.

我正在尝试创建一个库存系统。我有三个脚本:Player、GoundItem和ItemObject。播放器脚本将我与之碰撞的对象添加到清单中。GoundItem脚本附加到游戏世界中的对象,而ItemObject Scripable对象保存项目的属性。我面临的问题是,当我收集第四件物品时,即使它是可以堆叠的,它也会把它放在不同的位置。


[Header("Inventory")]
public int inventoryMax;
public List<ItemObject> inventory = new List<ItemObject>();

private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("GroundItem"))
{
if (inventory.Count < inventoryMax)
{
if (collision.GetComponent<GroundItem>().item.stackable && inventory.Count > 0)
{
bool addedToStack = false;
Debug.Log("1");
for (int i = 0; i < inventory.Count; i++)
{
Debug.Log(collision.GetComponent<GroundItem>().item.itemName);
if (inventory[i].itemName == collision.GetComponent<GroundItem>().item.itemName)
{
Debug.Log("2");
inventory[i].amount += collision.GetComponent<GroundItem>().item.amount;
Destroy(collision.gameObject);
addedToStack = true;
break;
}
if(!addedToStack)
{
Debug.Log("3");
inventory.Add(collision.GetComponent<GroundItem>().item);
Destroy(collision.gameObject);
break;
}
}
}
else if(inventory.Count <= 0)
{
Debug.Log("4");
inventory.Add(collision.GetComponent<GroundItem>().item);
Destroy(collision.gameObject);
}
}
else
{
Debug.Log("Inventory is Full");
}

}
}

[CreateAssetMenu(fileName ="NewItem", menuName ="Items/Item")]
public class ItemObject : ScriptableObject
{
public string itemName;
public Sprite itemSprite;
public int amount;
public bool stackable;

}

public class GroundItem : MonoBehaviour
{
public ItemObject item;

public SpriteRenderer groundItemSpriteRenderer;
public TextMeshPro groundItemAmountText;

private void Start()
{
groundItemAmountText.SetText(item.amount.ToString());
groundItemSpriteRenderer.sprite = item.itemSprite;
}


}

1- When I check with debug logs, I get the following results: When I collect the first item, it shows 4, which is correct because the inventory is empty initially and it doesn't enter the first condition (if (collision.GetComponent().item.stackable && inventory.Count > 0)).

1-当我检查调试日志时,我得到以下结果:当我收集第一个项目时,它显示4,这是正确的,因为库存最初是空的,并且它没有进入第一个条件(if(collision.GetComponent().item.stackable&&inventory.Count>0))。


2- When I collect the second item of the same type, it shows 1-2, which is correct because (inventory[i].itemName == collision.GetComponent().item.itemName) condition is met.

2-当我收集相同类型的第二个项目时,它显示1-2,这是正确的,因为(Inventory[i].itemName==Collision.GetComponent().item.itemName)条件满足。


3- When I collect the third item (of a different type), it shows 1-3, which is correct because the (inventory[i].itemName == collision.GetComponent().item.itemName) condition is not met.

3-当我收集第三项(不同类型的)时,它显示1-3,这是正确的,因为(Inventory[i].itemName==Collision.GetComponent().item.itemName)条件不满足。


4- However, when I collect the fourth item, it again shows 1-3. What could be the reason for this?

4-然而,当我收集第四件物品时,它再次显示1-3。这可能是什么原因呢?


I hope I've explained it well. These are the messages I received when I checked with debug logs. Thank you.

我希望我已经解释得很好了。这些是我在查看调试日志时收到的消息。谢谢。


更多回答

because unless the name matches your first inventory item, its going to be !addedtostack and dumped in a new slot immediately then broken out of the loop..

因为除非名称与您的第一个库存物品匹配,否则它将被添加到堆栈中,并立即转储到一个新的插槽中,然后中断循环。

优秀答案推荐

The core issue is that you're testing !addedToStack inside the loop that looks for existing stacks to add to. This means that if it's not the first item in the inventory then stacking fails and it appends to the inventory instead of continuing the search.

核心问题是您要在循环中测试!addedToStack,以查找要添加到的现有堆栈。这意味着如果它不是库存中的第一件物品,那么堆叠就会失败,它会添加到库存中,而不是继续搜索。


More broadly, there's a lot of redundant paths, repeated calls to collision.GetComponent<>(), duplicated code and so on.

更广泛地说,有很多冗余路径、对Collision的重复调用。GetComponent<>()、重复代码等等。


The purpose of this method seems to be: when you enter a tile/area that contains a "GroundItem" object, try to add that to inventory either by adding to an existing stack or appending to the inventory collection. If added, destroy the item in the game world. If not, report that the inventory is full.

此方法的目的似乎是:当您输入包含“GoundItem”对象的平铺/区域时,尝试通过添加到现有堆栈或附加到库存集合来将其添加到库存中。如果添加,则在游戏世界中销毁该物品。如果没有,则报告库存已满。


Let's implement it as close to that description as we can.

让我们尽可能接近该描述来实现它。


private void OnTriggerEnter2D(Collider2D collision)
{
// Check if there's an item to pick up
if (!collision.CompareTag("GroundItem"))
return;

// Get a copy of the picked up item to work with.
var pickingUp = collision.GetComponent<GroundItem>().item;
bool added = false;

// Try to add to existing stack
if (pickingUp.stackable && inventory.Count > 0)
{
for (int i = 0; i < inventory.Count && !added; i++)
{
if (inventory[i].itemName == pickingUp.itemName)
{
// Add amount to existing stack
Debug.Log($"Adding {pickingUp.amount}x {pickingUp.itemName} to existing stack in inventory slot #{i}.");
inventory[i].amount += pickingUp.amount;
added = true;
}
}
}

// Not stackable or new item, add to inventory
if (!added && inventory.Count < inventoryMax)
{
// Add to the end of the inventory.
Debug.Log($"Adding new {(pickingUp.stackable ? $"stack of {pickingUp.amount}x " : "")}{pickingUp.itemName} to inventory in slot #{inventory.Count}.");
inventory.Add(pickingUp);
added = true;
}

// Final disposition of the game object.
if (added)
// We picked it up, remove it from the game world.
Destroy(collision.gameObject);
else
// Didn't pick it up, leave it and report failure.
Debug.Log($"Inventory is full, leaving {(pickingUp.stackable ? $"{pickingUp.amount}x " : "")}{pickingUp.itemName}.");
}

Doing it this way makes it simpler to read, even if I hadn't peppered it with comments. Each if statement is now fairly self-contained, and follows the logical structure of the description I wrote above. (Also, fewer indents improve readability somewhat as well IMO.)

这样做会让它更容易阅读,即使我没有在上面塞满评论。每个if语句现在都相当独立,并且遵循我在上面编写的描述的逻辑结构。(此外,较少的缩进也在一定程度上提高了可读性。)


To demonstrate, here's the output from a quick test I did adding various items to an inventory limited to 3 slots:

为了演示,以下是我将各种物品添加到限制为3个插槽的库存中的快速测试的输出:



Adding new stack of 5x Potion to inventory in slot #0.

Adding new stack of 2x Scroll to inventory in slot #1.

Adding new Sword to inventory in slot #2.

Adding 2x Scroll to existing stack in inventory slot #1.

Inventory is full, leaving Shield.

Inventory is full, leaving 10x Berry.

Adding 2x Potion to existing stack in inventory slot #0.





If I were implementing this I'd probably create an Inventory class that can be attached as a component of the Player. When you're processing collisions on the player you can detect when the collision includes a potential pickup and hand it off to the inventory. This isolates all of the inventory management tasks to the Inventory class.

如果我要实现这一点,我可能会创建一个可以作为播放器组件附加的Inventory类。当您处理玩家的碰撞时,您可以检测碰撞是否包括潜在的拾取,并将其移交给库存。这将所有库存管理任务隔离到库存类。


Something like this (but adjusted to Unity of course):

大概是这样的(但当然是调整成了统一):


class Inventory
{
private readonly List<ItemObject> _items = new();

// Allow for resizable inventory
public int Size { get; private set; }

// Access to the item list from outside, for display and so on.
public IReadOnlyList<ItemObject> Items => _items;

public Inventory(int size)
{
Size = size;
}

// Add an item to the inventory, stacking as necessary.
public bool TryAddItem(ItemObject item)
{
// Locate compatible stack
if (item.stackable)
{
for (int i = 0; i < _items.Count; i++)
{
if (_items[i].itemName == item.itemName)
{
Debug.Log($"> Adding {item.amount}x {item.itemName} to existing stack at #{i}.");
_items[i].amount += item.amount;
return true;
}
}
}

// Check if we have any free slots
if (_items.Count >= Size)
{
Debug.Log($"> Inventory full, cannot add {(item.stackable ? $"{item.amount}x " : "")}{item.itemName}.");
return false;
}

// Append to inventory.
Debug.Log($"> Adding new {(item.stackable ? $"stack of {item.amount}x " : "")}{item.itemName} to inventory at #{_items.Count}.");
_items.Add(item);
return true;
}

// Remove an item (or multiple items from stack) by name.
public bool RemoveItem(string itemName, int count = 1)
{
// Find first matching item in inventory.
if (_items.Find(item => item.itemName == itemName) is ItemObject item)
return RemoveItem(item, count);
Debug.Log($"No {itemName} found in inventory.");
return false;
}

// Remove one or more of an item from the inventory.
public bool RemoveItem(ItemObject item, int count = 1)
{
// Locate item in inventory.
int index = _items.IndexOf(item);
if (index == -1)
{
Debug.Log($"Item not found in inventory.");
return false;
}

// Handle removing partial stacks.
if (item.stackable)
{
if (item.amount < count)
{
Debug.Log($"Cannot remove {count}x {item.itemName} from stack of {item.amount}.");
return false;
}
if (item.amount > count)
{
Debug.Log($"Removing {count}x {item.itemName} from #{index}.");
item.amount -= count;
return true;
}
}

// Remove item completely.
Debug.Log($"Removing {(item.stackable ? $"all {item.amount}x " : "")}{item.itemName} at #{index}.");
_items.RemoveAt(index);
return true;
}
}

And now your Player class has the following for inventory:

现在,您的Player类有以下清单:


// inventory, limited to 3 slots
readonly Inventory playerInventory = new(3);

private void OnTriggerEnter2D(Collider2D collision)
{
// Check if there's an item to collect.
if (collision.GetComponent<GroundItem>()?.item is ItemObject item)
{
if (playerInventory.TryAddItem(item))
Destroy(collision.gameObject);
}
// Check other collision types, like traps and such...
else if (collision.GetComponent<GroundTrap>() is GroundTrap trap)
{
// process trap
}
}

This makes it simpler to extend the functionality and operation of the Inventory class without further cluttering the Player class. You can even add multiple attached inventories - bags in the Player's inventory can have inventories of their own and so on.

这使得扩展Inventory类的功能和操作变得更简单,而不会进一步扰乱Player类。你甚至可以添加多个附加的库存--玩家的库存中的袋子可以有自己的库存,以此类推。


更多回答

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com