Read whole class documentation here 👇 :

Docs for RPG System


Watch gameplay in development here 👇 :

Gameplay for RPG System


Preview

This RPG game prototype is built in Unity and demonstrates a modular, extensible architecture for core RPG systems. Key features include player movement and navigation, a robust combat system (melee and ranged), AI-driven enemies with patrol and aggro behaviors, a progression and leveling system, experience and stat tracking, and interactive UI elements such as health bars and experience displays. The game also supports item pickups, weapon equipping, and scene transitions via portals.

Game mechanics revolve around point-and-lick movement, real-time combat with attack animations and range checks, stat-based damage calculation, and AI state machines for enemy behavior (patrolling, chasing, attacking, suspicion). The design leverages Unity’s component system, ScriptableObjects for data-driven configuration (e.g., weapons, progression), and interfaces for extensibility (e.g., IRaycastable for interactable objects). The UI updates dynamically to reflect player stats and game events, providing immediate feedback.

Technically, the project uses advanced C# concepts such as events, delegates, coroutines, serialization for saving/loading, and custom editor scripting. Developers gain experience in object-oriented design, Unity’s MonoBehaviour lifecycle, AI programming, and UI integration. Building this prototype teaches best practices in code organization, decoupling systems, and creating reusable gameplay modules—skills essential for professional Unity development.

Codebase

Character Progression & Leveling

Description:

Handles player and enemy stats, experience gain, and level-up logic. Stats are dynamically calculated based on progression data and modifiers, and level-up triggers effects and events.

public class BaseStats : MonoBehaviour
{
    [SerializeField] int startingLevel = 1;
    [SerializeField] CharacterType characterClass;
    [SerializeField] Progression progression = null;
    [SerializeField] GameObject levelUpParticleEffect = null;
    [SerializeField] bool shouldUseModifiers = false;

    LazyValue<int> currentLevel;
    public event Action onLevelUp;
    Experience experience;

    private void Awake()
    {
        experience = GetComponent<Experience>();
        currentLevel = new LazyValue<int>(CalculateLevel);
    }

    private void Start()
    {
        currentLevel.ForceInit();
    }

    private void OnEnable()
    {
        if (experience != null)
        {
            experience.onExperienceGained += UpdateLevel;
        }
    }

    private void OnDisable()
    {
        if (experience != null)
        {
            experience.onExperienceGained -= UpdateLevel;
        }
    }

    private void UpdateLevel()
    {
        int newLevel = CalculateLevel();
        if (newLevel > currentLevel.value)
        {
            currentLevel.value = newLevel;
            LevelUpEffect();
            onLevelUp();
        }
    }

    private void LevelUpEffect()
    {
        Instantiate(levelUpParticleEffect, transform);
    }

    public float GetStat(Stat stat)
    {
        return (GetBaseStat(stat) + GetAdditiveModifier(stat)) * (1 + GetPercentageModifier(stat) / 100);
    }
}
flowchart TD
    XP[Experience Gained] --> UpdateLevel
    UpdateLevel -->|Level Up| LevelUpEffect
    UpdateLevel -->|No Level Up| End
    LevelUpEffect --> onLevelUp

Stat Calculation with Modifiers

Description: