2
\$\begingroup\$

I am totally new to game development. I want to create a 2D Puzzle/Adventure point and click game similar to like 'Rooms' but scenes are connected. I have already done the inventory system but currently lack the functionality to be used with an object in a scene.

My question is how do I approach creating a system that will take in dynamic number of events? For example, I have key that will unlock the door, and the next scene I want to use it again without pre-programming this action specifically. I want to approach this in an efficient way so that I can use the system again for future games similar to this.

Can someone give me an idea because I am really stuck at this point. I don't want to program the game assigning individual scripts to each objects but rather do this systematically.

I am using Unity and C#

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Hey, first of all welcome here! Then, I haven't played that game Rooms, so I have hard times understanding what you're trying to achieve. Could you please explain the behaviour and logic you'd like to have? Thanks. \$\endgroup\$ – lvictorino Oct 20 '19 at 18:46
  • \$\begingroup\$ For example in the picture I can code the door to open with the key and a bool which is very straightforward, but I want to know how do I do this the correct way where In I can create a method that would accept a dynamic number of events (doors ,puzzles etc) that I can reuse over and over again for the game flow. Say I have 2 doors, and a variable set of puzzle requirements. \$\endgroup\$ – PeytonFarquhar Oct 21 '19 at 3:44
  • \$\begingroup\$ I'm so sorry. I still ton get it. What do you mean by "a dynamic number of events"? \$\endgroup\$ – lvictorino Oct 21 '19 at 8:38
  • \$\begingroup\$ Oh. I think I got it. Is your question more about "how to script the level logic and behaviour to know when every puzzle composing the level has been unlocked and validated" ? Like how to design a clever architecture that would let you know when the whole level is completed either you have 1 or 2000 puzzles to solve to complete it? \$\endgroup\$ – lvictorino Oct 21 '19 at 8:40
  • \$\begingroup\$ yes exactly on how to script this "how to script the level logic and behaviour to know when every puzzle composing the level has been unlocked and validated" . I just need some advice on how to approach this the correct way. \$\endgroup\$ – PeytonFarquhar Oct 21 '19 at 12:32
0
\$\begingroup\$

Polymorphism seems to be what you're looking for.

In the case you're describing, you could design your code to have a PuzzleManager object in your scene (that would inherit from MonoBehaviour), that would contain a list of Puzzle objects. The Puzzle could simply be an interface or a base class (if you're not comfortable with interfaces) with a unique method that would return a boolean bool IsPuzzleComplete(). Every class that would inherit from Puzzle would be in charge of the specific logic of the puzzle it describes.

In the case of a key/door puzzle, the KeyDoorPuzzle class would inherit from Puzzle and simply wait for the right key to be matched with the door it opens. When it happens, you just have to make the method IsPuzzleComplete() of the parent Puzzle class returning true. Now if you have that PuzzleManager object that is mainly a list of Puzzle it will be very simple to loop through the list and check the status of IsPuzzleComplete() of every contained Puzzle.

Bonus: You could even add a simple Observer pattern to this, to let your PuzzleManager be warned when a Puzzle is complete, without having to check the whole list of Puzzle every frame.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the help! Would definitely give this approach a try. \$\endgroup\$ – PeytonFarquhar Oct 21 '19 at 13:30
  • \$\begingroup\$ I hope it's clear enough and understandable. If you need more help you know where to find me :D \$\endgroup\$ – lvictorino Oct 21 '19 at 13:31
0
\$\begingroup\$

First, we need to make an architecture decision: Where does the logic "key opens door" belong to? Is it a behavior of Door that it can be opened by Key? Is it a behavior of Key that it is able to open Door? Or is it something which belongs into neither class and should instead be encapsulated in an entirely separate InteractionManager which knows how each inventory object interacts with each environment object in the game?

There are good arguments to be made for each of these solutions. Which one to pick is mostly a subjective choice. The only thing that's important is that you stay consistent throughout your game. If you implement the Door-Key interaction in this way but other interactions between inventory items and environment objects a different way, you are going to end in chaos. So make sure you pick a solution which plays well with all the use-cases you plan to have in your game.

For sake of this answer, let's assume you picked the solution where the interaction logic is implemented in the item. In that case I would create a MonoBehaviour Door which serves as a marker for environment objects which can be opened with a key and a MonoBehaviour Key which has a method Interact and a property Door fitsInto. The fitsInto property would then get assigned to the right door in the inspector.

The Interact method gets called when the player uses a key on a door. How to implement that is outside of the scope of this answers because it is heavily influenced by how your game's UI works.

The Key class would then work like this (untested code!):

public Door fitsInto; 

public void Interact(GameObject other) {
     // first, check if the other object actually has the "Locked" component:
     Locked locked = other.GetComponent<Locked>();
     if (locked == null) {
          // handle the case that this object isn't a door:
          Console.log("You can't find a keyhole on the " + other.name);
     } else {              
          // check if it's actually the "Locked" object for this key:
          if (locked != fitsInto) {
               Console.log("The key doesn't fit.");
          } else {
               Console.log("The key fits!");
               // TODO: Replace the closed door with an open door, or change its state from closed to open
          }
     }
}

But you can of course also do it the other way around and have Door implement the Interact method while also knowing which key opens it. (again, untested code!)

public Key openedBy; 

public void Interact(GameObject other) {
     // first, check if the other object actually has the "Key" component:
     Key key = other.GetComponent<Key>();
     if (key == null) {
          // handle the case that this object isn't a key at all:
          Console.log("You need a key to open this door, not a " + other.name);
     } else {              
          // check if it's the right key for this door:
          if (key != openedBy) {
               Console.log("The key doesn't fit.");
          } else {
               Console.log("The key fits!");
               // TODO: Replace the closed door with an open door, or change its state from closed to open
          }
     }
}

And last but not least, let's look at the Interaction Manager solution. This architecture was used by a lot of classic point and click adventures, like those based on the SCUMM engine by Lucas Arts.

This solution is usually based on a large table which maps pairs of inventory items and scenery objects to the functions which implement their interaction logic.

If you want to create a new interaction, you just add it to the table.

When the player uses an inventory item with a scenery object, you search that table for an entry with that item and that object, and execute the function it maps to.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.