DEV Community

Cover image for Building a 3D Game in Unity: From Concept to Completion
Jacob aberasturi
Jacob aberasturi

Posted on

Building a 3D Game in Unity: From Concept to Completion

The development of modern video games represents a unique convergence of multiple academic disciplines: computer science algorithms, psychological principles of player engagement, and interactive design theory. Through the development of "Parasite," a 3D roguelike game created in Unity, this article examines how theoretical computer science concepts materialize in practical game development, while considering their implications for player psychology and game design principles.

Theoretical Framework
Computer Science Foundations
The implementation of artificial intelligence in "Parasite" builds upon several fundamental computer science concepts:

  1. Graph Theory and Pathfinding
  • Application of A* algorithm for spatial navigation
  • Optimization of graph traversal in 3D space
  • Implementation of heuristic functions for performance enhancement
  1. Finite State Machines (FSM)
  • State transition logic for behavior modeling
  • Deterministic automata in practice
  • Event-driven architecture implementation

Psychological Framework
The AI system design incorporates key psychological principles:

  1. Player Engagement Theory
  • Challenge-skill balance maintenance
  • Flow state optimization
  • Progressive difficulty scaling
  1. Behavioral Psychology
  • Stimulus-response patterns in enemy behavior
  • Reinforcement learning principles
  • Player conditioning through consistent AI responses

Game Overview
Parasite is a 3D roguelike where players navigate through procedurally generated environments while facing AI-driven enemies. The game combines strategic combat with dynamic enemy behaviors, creating an engaging player experience.

Technical Implementation
1. A* Pathfinding System
One of our core technical challenges was implementing intelligent enemy movement. Here's how we approached it:

public class PathFinder : MonoBehaviour
{
    private Grid3D grid;
    private List<Node> openSet;
    private HashSet<Node> closedSet;

    public List<Vector3> FindPath(Vector3 startPos, Vector3 targetPos)
    {
        Node startNode = grid.NodeFromWorldPoint(startPos);
        Node targetNode = grid.NodeFromWorldPoint(targetPos);

        openSet = new List<Node> { startNode };
        closedSet = new HashSet<Node>();

        while (openSet.Count > 0)
        {
            Node currentNode = GetLowestFCostNode();
            // A* implementation logic
            // ...
        }

        return RetracePath(startNode, targetNode);
    }

    private Node GetLowestFCostNode()
    {
        // Implementation details
    }
}
Enter fullscreen mode Exit fullscreen mode

The A* implementation allows enemies to:

  • Find optimal paths to the player
  • Navigate around obstacles
  • Adapt to dynamic environment changes

2. Finite State Machine For Enemy AI
We implemented a robust FSM system to manage enemy behaviors:

public class EnemyFSM : MonoBehaviour
{
    private enum State
    {
        Idle,
        Patrol,
        Chase,
        Attack,
        Retreat
    }

    private State currentState;
    private Dictionary<State, System.Action> stateActions;

    void Start()
    {
        stateActions = new Dictionary<State, System.Action>()
        {
            { State.Idle, IdleState },
            { State.Patrol, PatrolState },
            { State.Chase, ChaseState },
            { State.Attack, AttackState },
            { State.Retreat, RetreatState }
        };
    }

    void Update()
    {
        stateActions[currentState].Invoke();
        CheckTransitions();
    }
}
Enter fullscreen mode Exit fullscreen mode

3. State Transitions and Decision Making
Each state implements specific behaviors and transition logic:

private void ChaseState()
{
    // Use A* pathfinding to chase player
    Vector3 pathToPlayer = pathFinder.FindPath(
        transform.position, 
        playerPosition
    );

    // Move along path
    MoveAlongPath(pathToPlayer);

    // Check attack range
    if (InAttackRange())
    {
        TransitionToState(State.Attack);
    }
}
Enter fullscreen mode Exit fullscreen mode

Performance Optimization
To maintain smooth gameplay, we implemented several optimization techniques:

Path Caching

private Dictionary<Vector3, List<Vector3>> pathCache;
private float pathUpdateInterval = 0.5f;

private void CachePath(Vector3 start, Vector3 end, List<Vector3> path)
{
    string key = GetPathKey(start, end);
    pathCache[key] = path;
}

Enter fullscreen mode Exit fullscreen mode

State Update Throttling

private float lastStateUpdate;
private float stateUpdateInterval = 0.2f;

void Update()
{
    if (Time.time - lastStateUpdate >= stateUpdateInterval)
    {
        stateActions[currentState].Invoke();
        lastStateUpdate = Time.time;
    }
}
Enter fullscreen mode Exit fullscreen mode

Challenges and Solutions
Challenge 1: Path Recalculation Overhead
Initially, our enemies recalculated paths every frame, causing performance issues. We solved this by:

  • Implementing path caching
  • Adding update intervals
  • Using path prediction for minor adjustments

Challenge 2: State Transition Edge Cases
We encountered bugs where enemies would rapidly switch between states. Solution:

  • Added state transition cooldowns
  • Implemented hysteresis in decision making
  • Created detailed state transition rules

Results and Metrics
Our optimizations led to significant improvements:

  • Reduced CPU usage by 40%
  • Maintained 60+ FPS with 20+ active enemies
  • Smooth state transitions with minimal stuttering

Lessons Learned

  1. Plan Your Architecture: A well-designed FSM saves time in the long run
  2. Profile Early: Regular performance profiling helps identify bottlenecks
  3. Optimize Intelligently: Focus on optimizations that impact player experience
  4. Test Edge Cases: State machines need robust testing for transition cases

Next Steps
Future improvements we're considering:

  • Implementing behavior trees for more complex AI
  • Adding dynamic difficulty adjustment
  • Expanding the state system for different enemy types
    Resources
    For those interested in implementing similar systems:

  • Unity's NavMesh Documentation

  • A* Pathfinding Project

  • Game Programming Patterns - State Pattern

Conclusion
Building Parasite was an exciting challenge that taught us valuable lessons about game AI implementation. The combination of A* pathfinding and FSM created engaging enemy behaviors while maintaining good performance.

Have you implemented AI systems in your games? I'd love to hear about your experiences and approaches in the comments below!

Game Trailer

Top comments (0)