QuestForge includes a flexible, game-agnostic reward system. No built-in reward types are provided — no currency, no items, no experience — because every game handles these differently.
The system gives you a base class to inherit from and two clean ways to connect a reward to your own game systems.
Rewards are granted automatically when a quest is completed. You do not need to call anything manually.
How It Works
The Quest asset holds a list of QuestRewardBase assets in its Rewards field. When QuestManager completes a quest it:
Calls CanGrantReward() on each reward — skips any that return false
Calls GrantReward() on each reward that passes validation
Fires the OnRewardGranted UnityEvent on QuestManager for each one granted
All the reward logic — what gets given and how — lives inside your reward asset. QuestManager never needs to know about your inventory, currency, or experience systems.
Creating a Custom Reward
Step 1 — Copy the template
Open ExampleReward.cs (located in Scripts/QuestSystem/Rewards/). Copy the file and rename both the file and the class to match your reward type — for example GoldReward, ExperienceReward, or ItemReward.
Step 2 — Set the create menu path
At the top of your new class, update the CreateAssetMenu attribute:
Below the fields inherited from QuestRewardBase, declare whatever your reward needs:
Step 4 — Implement GrantReward
This is the only method you must implement. It is called automatically when the quest completes. There are two recommended approaches:
Option A — Events (recommended)
Fire a Malbers event and wire it to your game system in the Inspector. This keeps your reward asset decoupled from your game code:
In the Inspector, connect OnGoldGranted to whichever method on your CurrencyManager, PlayerStats, or equivalent system that adds gold.
Option B — Direct reference (alternative)
Call your game systems directly from code:
Step 5 — Implement GetPreviewText
This is also required. It returns the short text shown in the quest UI before the player accepts the quest — e.g. the reward summary line:
Optional Overrides
CanGrantReward — Validation
Override this to prevent a reward from being granted under certain conditions. Return false to block it:
If CanGrantReward returns false, the reward is skipped silently. QuestManager will not fire OnRewardGranted for that reward.
RevokeReward — Abandonment / Failure
Override this only if your game design requires rewards to be taken back when a quest is abandoned or failed. The base implementation does nothing:
What QuestRewardBase Provides
Every reward asset automatically has these fields and helpers from the base class — you do not need to re-declare them:
Field / Method
Type
Description
rewardName
string
Display name shown in the quest UI
description
string
Tooltip or detail text
icon
Sprite
Icon shown in the rewards UI
OnRewardGranted
MEvent
Fired automatically on success — wire to sound/VFX
OnRewardFailed
MEvent
Fired automatically on failure
InvokeSuccessEvent(data)
Helper
Call this at the end of GrantReward
InvokeFailureEvent(reason)
Helper
Call this when validation fails
Creating the Reward Asset
Once your script compiles:
In the Project window, right-click → Create → Malbers Quest Forge → Rewards → [Your Reward Name]
Name it descriptively (e.g. Reward_100Gold)
Configure its fields in the Inspector — reward name, icon, amount, and any event connections to your game systems
Linking Rewards to a Quest
Select your Quest asset in the Project window
Find the Rewards list in the Inspector
Click + and drag in your reward asset (e.g. Reward_100Gold)
Add as many reward assets as needed — they all grant in sequence on completion
The rewards are displayed to the player in the quest journal and in the New Quest panel when the quest is first accepted, using the GetDisplayName(), GetIcon(), and GetPreviewText() values from each asset.
Examples - Common Reward Types to Build
Reward Type
Approach
Currency (gold, gems)
Fire IntEvent → CurrencyManager
Experience / Leveling
Fire IntEvent → PlayerStats
Item Grant
Fire MEvent → InventoryManager, or use direct reference with an ItemData ScriptableObject field
public override string GetPreviewText()
{
return $"+{goldAmount} Gold";
}
public override bool CanGrantReward(QuestInstance questInstance, QuestManager manager)
{
// Example: only grant if inventory has space
if (!InventoryManager.Instance.HasSpace()) return false;
return base.CanGrantReward(questInstance, manager);
}
public override void RevokeReward(QuestInstance questInstance, QuestManager manager)
{
OnGoldGranted?.Invoke(-goldAmount); // deduct the gold
}