Overview
Technical Analysis: CandyWorld - Idle Management Game
CandyWorld is an idle/management mobile game project we developed in Unity 3D, focusing on creating an automated production chain and non-linear progression. This project served as an in-depth study of various software architectures, design patterns, and performance optimizations for mobile platforms.
Architecture and Design Patterns
CandyWorld's architecture was carefully planned to ensure scalability, maintainability, and robustness. We utilized the State Machine Pattern to manage the behavior of various entities like players, customers, and production processes. This allowed for controlled state transitions and simplified debugging, leading to predictable and logical behaviors for NPCs (Idle → Find → Move → Buy → Leave). The Singleton Pattern was employed to centralize game control and manage essential systems such as audio (AudioManager), particles (ParticleManager), and UI (UiManager), ensuring efficient global access. Complementarily, the Component-Based Architecture was crucial for modularizing each building, character, and object, making it easier to add new features and maintain the code without impacting other parts of the system.
AI Helpers
Behavioral AI System: We developed NPCs with autonomous behavior and decision-making. Navigation was implemented using Unity NavMesh, providing natural and efficient pathfinding. This includes a customer patience and satisfaction system to influence the gameplay experience.
public enum AiStates { Idle, Find, Buy, Move, Leave };
void Find_Enter() {
targetShelf = Game_.instance.buildingsManager.shelves[Random.Range(0, Game_.instance.upgrades.shelfsUnlocked)].GetComponent<Shelf_>();
NavMesh.SamplePosition(targetShelf.transform.position, out NavMeshHit hit, 10, NavMesh.AllAreas);
target = hit.position;
agent.SetDestination(target);
// Dynamic product preference system
switch (targetShelf.tag) {
case "LollipopShelf":
productBubbleImage.sprite = productsSprites[0];
break;
// Visual feedback for customer intent
}
fsm.ChangeState(AiStates.Move);
}
Autonomous Helper AI System: We created an automation system with NPCs that optimize production independently, with a dynamic task prioritization based on game state.
void Find_Enter() {
Vector3 target = Vector3.zero;
if (productsHolder.childCount > 0) {
targetShelf = FindShelf(); // Smart shelf selection algorithm
} else {
targetMachine = FindMachineWithMoreProducts(); // Production bottleneck detection
if (targetMachine != null) {
target = targetMachine.outShelf.transform.position;
}
}
if (target != Vector3.zero) {
NavMesh.SamplePosition(target, out NavMeshHit hit, 20, NavMesh.AllAreas);
agent.SetDestination(hit.position);
}
}
Economy
Automated Production System: We created a complete production pipeline, from plant and ingredient gathering to product transformation by machines, and finally, sales. Coroutines were used to manage asynchronous processes, and an automatic supply/demand balancing system was implemented to keep the game's economy dynamic.
IEnumerator Factory() {
yield return new WaitForSeconds(1);
if (inShelf.GetLastCollectable() != null) {
Ingredient_ ingredient = inShelf.GetLastCollectable() as Ingredient_;
IngredientType ingredientType = ingredient.type;
for (int i = 0; i < productsPerIngredient; i++) {
// Animated production sequence
LeanTween.moveLocalY(piston, 0, .2f).setEase(LeanTweenType.easeInCubic).setLoopPingPong(1);
yield return new WaitForSeconds(.05f);
Product_ currentProduct = Instantiate(product, productStartPoint.position, transform.rotation);
currentProduct.flavor = ingredientType;
currentProduct.setFlavorMaterial();
// Conveyor belt animation with UV scrolling
LeanTween.value(gameObject, 0, 1, Game_.instance.upgrades.machineSpeedValue).setOnUpdate((float val) => {
conveyourRenderer.material.mainTextureOffset = new Vector2(0, -val * 2);
});
yield return new WaitForSeconds(Game_.instance.upgrades.machineSpeedValue);
outShelf.SpawnCollectable(currentProduct);
}
}
StartCoroutine(Factory()); // Recursive loop for continuous production
}
Dynamic Progression System: The game progression was carefully balanced using progression curves (AnimationCurve) and mathematical formulas for the upgrade system. This allowed for gradual and rewarding content unlocking, keeping players engaged long-term.
public int holdItensValue {
get {
return (int)Game_.instance.priceManager.holdItens.Evaluate((float)holdItensLevel / (maxLevel - 1));
}
}
public float machineSpeedValue {
get {
return Game_.instance.priceManager.machineSpeed.Evaluate((float)machineSpeedLevel / (maxLevel - 1));
}
}
Data Management System: A Persistent Save/Load System: To ensure player data persistence, we implemented an automatic data serialization system. A debounce system was integrated to optimize saves, and async/await operations were used to ensure save/load operations were non-blocking, preventing freezes in the user experience.
Contextual Tutorial: We developed a step-by-step tutorial system with player action validation. Tutorial progress is persisted via PlayerPrefs, and dynamic UI with visual indicators offers non-intrusive guidance, allowing players to learn at their own pace without breaking the game's flow.
Optimizations and Performance
- Object Pooling: Significantly reduced garbage collection for frequently instantiated particles and objects.
- Tweening System: Used for performant animations, resulting in fluid visual feedback without impacting frame rate.
- Modular Loading: A building manager system that activates/deactivates objects as needed, optimizing memory usage through lazy loading.
Results
Technical Challenges Solved
During CandyWorld's development, we faced and resolved complex challenges such as economic balancing (through mathematical curves), mobile performance optimization (rendering and memory), creating a robust save system (preventing data loss with debouncing), developing behavioral AI for natural and non-repetitive NPCs, and implementing a non-intrusive tutorial.
Results and Technical Metrics
CandyWorld achieved consistent 60 FPS on mid-range devices and an optimized memory footprint, staying below 200MB. The modular architecture ensures high scalability for easy content addition and excellent maintainability, with clear separation of responsibilities.
This project demonstrates my proficiency in software architecture, mobile optimization, AI implementation, complex game design systems, and third-party SDK integration essential competencies for developing commercial and high-performance games.