0
\$\begingroup\$

It's hard for me to explain my question with an example. But essentially, I have a game with many craftable items. Each item is a prefab. Each item has many unique scripts and functions on it.

Sometimes these items interact with each other (an Axe cuts Tree spawns Wood). So in either of their scripts, you need to reference the other ones.

What I did first was create one of each object in the hierarchy and move them 999999 units away. So basically I have a 100 items living very far away from the player. And so I would always use Find("Wood") to get a reference to the Wood to spawn some when the Tree is hit with the Axe (just an example).

Then I was told using Find is bad and you should rather use assignments in the unity editor (serialized fields). So I removed all my Find()s and replaced then with editor references to the prefabs (I drag the prefab into the field).

But now my problem is that editor-assigned game objects aren't always that great. These objects don't run through their Awake() and Start() setups. They also aren't "alive" yet. So you run into many issues trying to query stuff from an object that doesn't exist yet. A lot of references to stuff that is in the Start() is not being run so a lot of the item's code crashes without these references. So you have to write this "if not instantiated: Instantiate()" type of logic. All in all, this is honestly becoming a bigger mess than "Find" was.

Is it wrong to just have a 100 spawned items living super far from the player? Is this a common game design idea or how exactly are these "keeping references of things" solved? Because I don't feel the Unity editor assignment is exactly the solution.


I realized a better example might be required, so here is one. Each item has its own script. Each script has a TryCraft() function. This function checks if the player has the correct amount of resources or rules (like standing near a Builders Bench) to craft this item. If the player does not, we throw a popup explaining what is missing.

Notice we need 2 references here, a reference to the player's current inventory and a reference to the popup component. Both of these references are set up in my Start().

So now, if I assign this Axe prefab to the UI craft button (through a serialized field) and the player tries to run TryCraft() on the Axe. Now the Axe complains because it doesn't know what playerInventory or popupComponent is. Because it never ran its own Start(). You see my point, I don't need a instance of the Axe just yet, I just need to run TryCraft() and that will create the instance if the player has the right amount of items. And I can't really move this logic somewhere else because some items are simple (you just need 2 x Grass) but other items are a lot more complex (you need to have 1 x Iron and be standing next to a Builders Bench to create a Bucket).

\$\endgroup\$
1
  • 3
    \$\begingroup\$ Take a look at ScriptableObject, which might be better fit for your needs than game objects. \$\endgroup\$
    – msell
    Commented Feb 17 at 8:55

2 Answers 2

2
\$\begingroup\$

Is it wrong to leave references objects in the game world like 99999 units away

Nope, it is not wrong, many games actually hide references object in unreachable place. Let me give you examples on recent games.

Lethal company hide the reference to char model in unreachable place of the map, which was found only by using modded version of the game. enter image description here

Genshin impact hide their texture palette below the ocean, which is reachable only by using glitches. The texture palette size increases when new region is added to the game.

enter image description here

Location of the texture palette in the game

enter image description here

\$\endgroup\$
0
\$\begingroup\$

The main question is one of efficiency. Any object created will consume memory and CPU resources.

For 100 simple objects in a small game, this waste may not matter.


If your overall design requires all objects to already exist, there is a flaw in the design.


The best solution is to not use the objects themselves to convey information, but shadow the information in a single place like the player object: (could be stored elsewhere)

Find("Wood") becomes a lookup to an array stored on the player object indicating the count of the objects of that type collected.

Since the array always exists and has a default value for each item, null references and look-ups are not a problem.


Objects should be visual representations of collectable items and not the storage mechanisms themselves.


Chop down a tree, create via instantiation collectable "Wood" object(s). When the player collides with the "Wood" object the object is destroyed, and 1 is added to the player's resource array in the "Wood" slot.

Note that each slot "type" should be defined by an Enum value: "Wood" = 0, "Iron" = 1, ...= 99 for the 100 types possible.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .