I’m creating a security number pad for access to a door. The pad itself is working fine. The problem I am trying to solve is how to open a specific door in the scene vs. all of them. Current the setup is like this:
The player enters a trigger that to opens the number pad widget
The player enters the code and the widget logic determines whether the access is granted, if so, then…..
The next part is where my question begins. Getting a refence to the door class then executing the open door custom event works but it opens every door. To fix this, I created an interface used by the door and the widget. When the trigger is activated, it sends a message to the number pad widget that passes a reference to the door. From there, when the correct code is entered it sends a message back to the specific door that was passed in. This seem kind of hacky, is there a more elegant solution or is this approach fine?
Create a dispatcher in the pad blueprints that executes when the correct code is entered. In the door reference that pad specifically and bind the unlock function to the dispatcher. This reference has to be exposed to be assigned per instance.
This way any door can listen to a specific pad, and the pad can work with anything else.
If you really want to avoid the hard reference for some reason, then in the pad expose a actor variable that is exposed to reference the specific door actor and check for the interface.
I don’t think you need an interface here, esp using it on both the door and widget. It adds another layer of indirection/upkeep that may be unnecessary in this situation… is it necessary to keep the objects de-coupled like that? Some questions to ask: will the widget always ref a door, could you just use the base BP_Door’s signature to do the call? will the door trigger always ref the same UI widget?
If you want/need the decoupling then keep the interface… what you’ve done works fine. I would not use the same interface for both tho. I would do separate interfaces like BPI_OpenableDoor, and BPI_DoorLockWidget.
…is there a more elegant solution or is this approach fine?
Both…
Any working solution is “fine” in my book.
There is always a more elegant solution and I’m not calming mine will be but I’ll give it a shot:
Make a public DoorActor variable in the pad widget. You can use a IOpenable interface here if you think you might use the pad on other unrelated objects.
When opening the padWidget pass the DoorActor to it from whatever is interacting with the door.
Use this DoorActor reference to check the code validity and open it.
Bonus:
Make as few references to the widget as possible - don’t make the door “know” about the UI. Usually whichever object has created the UI is also responsible to hide/show it and feed it objects (doors in your case) Reference whatever you like from the widgets.
Bonus2:
Try hiding and sowing the same pad widget without destroying it. Just reset it and give it another door to control.
Hope this somewhat helps. Ofc you can go the route that each door has it’s own widget component but that is if you want to place your widgets in the world.
Thanks for the responses. I’m not sure which direction to take. But I can say that it would be nice to leave the number pad separate from the door since at some point I’m going to have chests, lockers and computer access terminals. With that said, any thoughts on which solution would be best in this case?
Imo I’d keep the pad separate from the door and just broadcast when the correct conditions are met. Then any actor that should respond (door, chest, locker, terminal, etc) can hold a reference to that specific pad instance and cast to bind to its dispatcher.
The dispatcher should be on the parent class of the pad.