so I spent two days to realize i should just use a interface but can some one explain if its possible to make this work without interface what about using two overlap components one for left ai and one to right for player?
there are other ways, ActorComponent or Tags but they both require change and are probably worse. An interface is quick and easy to implement
1. The Core Problem We’re Solving
Your door is reacting to two possible actors overlapping it:
-
Player -
AI Buyer
But Unreal’s OnComponentBeginOverlap only fires once per actor — and actors can enter in any order.
So your biggest enemy is this:
“Who overlaps first, and what if the other actor isn’t there yet?”
If you run logic immediately when one enters, you’ll hit Accessed None or invalid reference errors.
So the challenge was:
-
Track both actors independently
-
Only run the “handshake logic” when both are present
-
Avoid re-triggering it multiple times
2. Why the HasTriggered Boolean Exists
That’s our safety lock.
Without it, Unreal fires multiple overlaps — e.g.:
-
AI steps in → overlap fires
-
Player steps in → overlap fires again
-
Maybe the AI slightly moves → fires again
-
Boom: widget spam, logic repeats, errors pile up
So we add a simple gatekeeper:
if NOT HasTriggered:
(run logic)
else:
ignore
This is a classic pattern in UE and all event-driven systems.
3. Why We Use a Sequence
Because you want to check both AI and Player overlaps every time an overlap happens.
Unreal only gives you one Other Actor per overlap event — but you don’t know who it is until you test.
So the Sequence node splits execution:
Exec 0 → Try AI Cast
Exec 1 → Try Player Cast
Each “exec” checks one possibility separately — it’s like saying:
“Let’s see if this was an AI. No? Okay, maybe it was the Player.”
That’s way cleaner and safer than putting both casts on one line.
4. Why Each Side Calls CheckBothOverlap()
Because each overlap event could be the second half of the handshake.
-
If the AI enters first, we store them and wait for the player.
-
If the Player enters first, we store them and wait for the AI.
Then, every time a new overlap happens, we call:
CheckBothOverlap()
That function checks:
if (PlayerRef != None) AND (CurrentCustomer != None)
When both exist → the deal is ready.
That means no matter who walks in first, it always synchronizes cleanly.
5. Why It’s So Reliable
This pattern combines three concepts:
| Concept | Why it matters |
|---|---|
NOT HasTriggered |
Prevents duplicate firings |
Sequence |
Separates logic for AI vs Player |
CheckBothOverlap() |
Waits until both actors exist |
These three together create safe, event-driven interaction logic — no timers, no hard dependencies, no invalid refs.
It’s exactly how professionals design door triggers, quest givers, or dialogue initiators in open-world games.
Real-world Dev Insight
This logic pattern — it’s universal:
-
RPG quest givers (player + NPC proximity)
-
Store counters (cashier + customer detection)
-
AI conversations
-
Door unlock systems (key + player overlap)
-
Coop puzzles (two players step on plates)
So by understanding this pattern, you’ve learned a core interaction architecture you’ll reuse in every future UE project.
