Migrating AI from Python to C#/C++

Game Dev 101

Krisnamughni
9 min readJul 15, 2023

Python’s high-level nature and dynamic typing make it ideal for AI development, allowing quick prototyping and experimentation. However, in the context of game development, Python’s performance limitations become apparent. Games require efficient processing and low-latency responses, making languages like C# and C++ more suitable for performance-critical components, including AI algorithms.

By migrating Python AI to C#/C++, game developers can leverage the performance advantages of these languages while harnessing the rich ecosystem of Unity and Unreal Engine. This migration ensures smoother integration of AI functionality within the game environment.

In game development, the choice of programming language between Python, C#, and C++ for machine learning or AI models can have several differences. Here are some key considerations:

  • Python is widely used for machine learning and AI development, offering a simple and expressive syntax with a vast ecosystem of libraries such as NumPy, TensorFlow, and PyTorch. It provides a high-level programming environment that allows for quick prototyping and experimentation. Python’s extensive community support, numerous online resources, and integrated development environments (IDEs) make it accessible to developers. However, its interpreted nature may result in slower performance compared to compiled languages like C# and C++. Python is suitable for tasks such as data preprocessing, model training, and offline processing in game development with AI.
  • C# is the primary language used in Unity game engine, offering a well-integrated development environment. It provides good performance and productivity balance, with a syntax similar to Java and strong support for object-oriented programming. Unity’s IDE provides seamless integration with game-related functionality and APIs, making it convenient for AI model development in Unity games. C# is commonly used for scripting game behavior, including AI logic, in real-time game development.
  • C++ is a powerful, low-level language widely used in Unreal Engine game development. It offers exceptional performance and control over system resources, making it suitable for computationally intensive AI tasks. C++ follows a multi-paradigm approach, providing both low-level and high-level features. While it has a steeper learning curve compared to Python and C#, it offers extensive libraries and APIs specific to game development within Unreal Engine. C++ is often used for implementing complex AI systems, including behavior trees, pathfinding algorithms, and physics simulations.

Each language has its strengths and considerations in game development. Python excels in its simplicity and extensive machine learning ecosystem, while C# and C++ offer better performance and integration capabilities within their respective game engines. The choice of language depends on project requirements, performance needs, familiarity with the language, and the features and support provided by the chosen game engine.

To facilitate comprehension of the distinctions among Python, C#, and C++, I have created a comparative table presented below:

Migrating Python AI Models to C# in Unity

Unity is a widely used game engine that supports C# as its primary scripting language. To migrate a Python AI model to C# in Unity, the following steps can be followed:

  1. Understand the Python AI Model: Study the Python AI model code to gain a comprehensive understanding of its functionality, including its inputs, outputs, and any additional dependencies.
  2. Set Up Unity Project: Create a new Unity project or open an existing one and ensure that the necessary packages, plugins, or libraries for AI integration are installed.
  3. Convert Python Code to C#: Start converting the Python AI model code to C#. Begin by mapping Python libraries or modules used in the AI model to their equivalent C# counterparts, ensuring that the functionality is preserved.
  4. Replicate AI Model Behavior: Recreate the behavior of the AI model in C# using Unity’s C# scripting capabilities. Utilize Unity’s APIs and built-in AI functionality to implement the required features, such as decision-making, pathfinding, or behavior trees.
  5. Testing and Integration: Test the migrated AI model in Unity by integrating it into the game environment. Validate the functionality and performance of the AI model within the game to ensure proper integration.

Migrating Python AI Models to C++ in Unreal Engine

Unreal Engine, another popular game engine, supports C++ as its primary programming language. To migrate a Python AI model to C++ in Unreal Engine, consider the following steps:

  1. Understand the Python AI Model: Analyze the Python AI model’s codebase to gain a thorough understanding of its structure, dependencies, and functionality.
  2. Set Up Unreal Engine Project: Create a new Unreal Engine project or open an existing one. Ensure that the required plugins or libraries for AI integration are installed.
  3. Translate Python Code to C++: Begin converting the Python AI model code to C++. Identify the necessary C++ classes, structures, and libraries that will replicate the Python model’s behavior.
  4. Implement AI Functionality: Utilize Unreal Engine’s AI framework and C++ programming capabilities to recreate the AI model’s behavior. Leverage the available features, such as behavior trees, navigation systems, and sensory perception, to replicate the desired AI behavior.
  5. Integration and Testing: Integrate the C++ AI model into the Unreal Engine game environment. Conduct thorough testing to ensure the AI’s functionality and performance meet the desired requirements.

Developing AI models for game development using C# or C++ can be a rewarding experience, even if you have primarily worked with Python before. While the syntax and libraries may differ, the core concepts of AI development remain the same. Here’s a step-by-step guide to help you get started:

  • Acquaint Yourself with C# or C++: Familiarize yourself with the basics of C# or C++ programming languages. Understand their syntax, data structures, and object-oriented programming concepts. Resources like tutorials, online courses, or documentation specific to game development can help you grasp the language essentials.
  • Understand AI Concepts: Gain a solid understanding of AI concepts relevant to game development. Key areas to explore include decision-making algorithms (such as decision trees or behavior trees), pathfinding algorithms (like A* or Dijkstra’s algorithm), and machine learning techniques (e.g., neural networks or reinforcement learning). Study relevant AI resources and documentation to build a strong foundation.
  • Explore Game Development Frameworks: Dive into game development frameworks that support C# or C++. For example, Unity provides extensive support for C#, and Unreal Engine uses primarily C++. Familiarize yourself with these frameworks and their AI-related features, including built-in AI systems, pathfinding tools, and behavior trees. Understand how to integrate AI models into these frameworks to create interactive and intelligent gameplay.
  • Leverage AI Libraries: Although Python has a wide range of AI libraries, C# and C++ also have their own libraries that can be utilized for AI development in game development environments. For C#, explore libraries like Accord.NET, AForge.NET, or ML.NET. In the case of C++, consider libraries such as TensorFlow, OpenAI Gym, or FastAI. These libraries provide powerful tools for AI-related tasks, such as machine learning, computer vision, or natural language processing.
  • Replicate Python AI Models: Start by replicating the AI models you have previously implemented in Python using C# or C++. Begin with simpler models and gradually move towards more complex ones. Pay attention to translating the logic and algorithms from Python to the chosen language, ensuring the core functionality remains intact. Make use of the AI libraries mentioned earlier to simplify the process and save development time.
  • Utilize Framework-Specific AI Tools: Take advantage of the AI tools and features provided by game development frameworks like Unity or Unreal Engine. These frameworks often have built-in components and systems designed for AI integration. For example, Unity’s ML-Agents toolkit facilitates training AI agents using reinforcement learning. Explore the AI documentation and resources provided by the frameworks to maximize efficiency and leverage existing functionalities.
  • Experiment and Iterate: Game development is an iterative process, and the same holds true for AI integration. Experiment with different approaches, algorithms, and parameters to optimize your AI models. Test and refine the AI behavior within the game environment to ensure it aligns with your intended gameplay experience. Seek feedback from playtesters or colleagues to fine-tune your models further.
  • Continuously Learn and Grow: Stay updated with the latest advancements in AI and game development. Participate in online communities, forums, or meetups to connect with fellow developers and learn from their experiences. Attend workshops or conferences focused on AI in gaming to expand your knowledge and gain insights from industry experts.

Example : Enemy Behavior in a Platformer Game

In a 2D platformer game, you want to create AI-controlled enemies that exhibit different behaviors based on the player’s position and actions. The AI should determine whether the enemy should pursue the player, stay idle, or retreat.

Python Code:

class EnemyAI:
def __init__(self, player_position, player_action):
self.player_position = player_position
self.player_action = player_action

def decide_behavior(self):
distance_to_player = calculate_distance(self.player_position, self.enemy_position)

if distance_to_player < 10 and self.player_action == "Attack":
return "Retreat"
elif distance_to_player < 5 and self.player_action == "Retreat":
return "Pursue"
else:
return "Idle"

# Other helper functions
def calculate_distance(self, position1, position2):
# Calculate the Euclidean distance between two positions
return math.sqrt((position1[0] - position2[0])**2 + (position1[1] - position2[1])**2)

# Example usage
player_position = (50, 30)
player_action = "Attack"

# Create an instance of the enemy AI
enemy_ai = EnemyAI(player_position, player_action)

# Decide the behavior of the enemy
enemy_behavior = enemy_ai.decide_behavior()

print("Enemy Behavior:", enemy_behavior)

C# Code:

using System;
using System.Numerics;

public class EnemyAI
{
private Vector2 playerPosition;
private string playerAction;

public EnemyAI(Vector2 playerPosition, string playerAction)
{
this.playerPosition = playerPosition;
this.playerAction = playerAction;
}

public string DecideBehavior()
{
float distanceToPlayer = CalculateDistance(playerPosition, enemyPosition);

if (distanceToPlayer < 10 && playerAction == "Attack")
{
return "Retreat";
}
else if (distanceToPlayer < 5 && playerAction == "Retreat")
{
return "Pursue";
}
else
{
return "Idle";
}
}

// Other helper functions
private float CalculateDistance(Vector2 position1, Vector2 position2)
{
return MathF.Sqrt(MathF.Pow(position1.X - position2.X, 2) + MathF.Pow(position1.Y - position2.Y, 2));
}
}

public class Program
{
public static void Main(string[] args)
{
Vector2 playerPosition = new Vector2(50, 30);
string playerAction = "Attack";

// Create an instance of the enemy AI
EnemyAI enemyAI = new EnemyAI(playerPosition, playerAction);

// Decide the behavior of the enemy
string enemyBehavior = enemyAI.DecideBehavior();

Console.WriteLine("Enemy Behavior: " + enemyBehavior);
}
}

C++ Code:

#include <iostream>
#include <cmath>

class EnemyAI
{
private:
Vector2 playerPosition;
std::string playerAction;

public:
EnemyAI(Vector2 playerPosition, std::string playerAction)
{
this->playerPosition = playerPosition;
this->playerAction = playerAction;
}

std::string DecideBehavior()
{
float distanceToPlayer = CalculateDistance(playerPosition, enemyPosition);

if (distanceToPlayer < 10 && playerAction == "Attack")
{
return "Retreat";
}
else if (distanceToPlayer < 5 && playerAction == "Retreat")
{
return "Pursue";
}
else
{
return "Idle";
}
}

private:
float CalculateDistance(Vector2 position1, Vector2 position2)
{
return std::sqrt(std::pow(position1.X - position2.X, 2) + std::pow(position1.Y - position2.Y, 2));
}
};

int main()
{
Vector2 playerPosition(50, 30);
std::string playerAction = "Attack";

// Create an instance of the enemy AI
EnemyAI enemyAI(playerPosition, playerAction);

// Decide the behavior of the enemy
std::string enemyBehavior = enemyAI.DecideBehavior();

std::cout << "Enemy Behavior: " << enemyBehavior << std::endl;

return 0;
}

In this example, we define an EnemyAI class that takes the player's position and action as inputs. The decide_behavior method calculates the distance between the enemy and the player using the calculate_distance helper function. Based on the distance and the player's action, the AI decides the enemy's behavior - whether to pursue the player, stay idle, or retreat.

Note that the calculate_distance function calculates the Euclidean distance between two positions using the Pythagorean theorem. You can adjust the threshold values and conditions in the decide_behavior method based on your specific game requirements. This Python code can serve as a starting point for implementing AI behavior in a 2D platform game. To adapt it for C# or C++, you can follow the steps mentioned earlier in this article and translate the Python code into the respective language syntax while maintaining the same logic and functionality.

In the C# and C++ code, the EnemyAI class and its methods are implemented similarly to the Python version. The CalculateDistance helper function calculates the distance between two positions using the Euclidean distance formula. To run the code in C#, create a new C# console application project and replace the default code with the provided code.

To run the code in C++, you would need to have the necessary headers and classes defined (e.g., Vector2). Ensure that you include the appropriate headers and set up a proper build environment to compile and execute the code.

Remember to adapt the code as per your specific requirements, such as adjusting the threshold values and conditions, incorporating additional game logic, or integrating with a 2D platform game framework.

--

--

Krisnamughni

Most of the time, we see only what we want to see, or what others tell us to see, instead of really investigate to see what is really there.