Image Generation
Generate AI images using PlayKit_AIImageClient and integrate them into Unity games
Image Generation
PlayKit_AIImageClient allows you to generate images from natural language descriptions, ideal for dynamic content generation, prototyping, or temporary art assets in games.
For example, you can generate different character portraits based on player choices, or create unique textures for procedurally generated dungeons.
Before You Begin
- Make sure you've completed SDK initialization
- Understand that image generation may take longer (typically 5-30 seconds)
- Generated images are in Base64-encoded PNG format
Create an Image Client
Use the factory method to create an image generation client:
// Use default model
var imageClient = PlayKitSDK.Factory.CreateImageClient();
// Specify model
var imageClient = PlayKitSDK.Factory.CreateImageClient("dall-e-3");Generate a Single Image
Use the GenerateImageAsync() method to generate a single image:
using Cysharp.Threading.Tasks;
using PlayKit_SDK;
using PlayKit_SDK.Public;
using UnityEngine;
using UnityEngine.UI;
public class SimpleImageGeneration : MonoBehaviour
{
[SerializeField] private Image displayImage;
[SerializeField] private Button generateButton;
private PlayKit_AIImageClient imageClient;
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
generateButton.onClick.AddListener(() => GenerateImage().Forget());
}
async UniTaskVoid GenerateImage()
{
generateButton.interactable = false;
// Generate image
PlayKit_GeneratedImage result = await imageClient.GenerateImageAsync(
prompt: "a futuristic sci-fi city at sunset, digital art",
size: "1024x1024",
seed: null, // Random seed
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
// Convert to Sprite and display
Sprite sprite = result.ToSprite();
displayImage.sprite = sprite;
Debug.Log($"Original prompt: {result.OriginalPrompt}");
Debug.Log($"Revised prompt: {result.RevisedPrompt}");
}
else
{
Debug.LogError("Image generation failed");
}
generateButton.interactable = true;
}
}Image Sizes
The SDK supports multiple image sizes:
Standard Sizes
"256x256"- Small, fast generation"512x512"- Medium size"1024x1024"- High quality square images
Widescreen Sizes
"1792x1024"- Widescreen landscape"1024x1792"- Widescreen portrait
// Generate widescreen image
var wideImage = await imageClient.GenerateImageAsync(
prompt: "a vast landscape with mountains",
size: "1792x1024",
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);Different sizes may have different generation times and credit costs. Larger images typically take longer and cost more credits.
Generate Multiple Images
Use the GenerateImagesAsync() method to generate multiple images at once:
using System.Collections.Generic;
public class BatchImageGeneration : MonoBehaviour
{
private PlayKit_AIImageClient imageClient;
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
}
public async UniTask GenerateMultipleImages()
{
// Generate 4 images
List<PlayKit_GeneratedImage> images = await imageClient.GenerateImagesAsync(
prompt: "fantasy character portrait, digital art",
count: 4,
size: "512x512",
aspectRatio: null,
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (images != null && images.Count > 0)
{
Debug.Log($"Successfully generated {images.Count} images");
for (int i = 0; i < images.Count; i++)
{
Sprite sprite = images[i].ToSprite();
// Display or save image
DisplayImage(sprite, i);
}
}
}
void DisplayImage(Sprite sprite, int index)
{
// Implement image display logic
}
}Using Seed Values
Seed values can generate reproducible images. Using the same prompt and seed produces similar images:
public class SeededImageGeneration : MonoBehaviour
{
private PlayKit_AIImageClient imageClient;
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
}
public async UniTask GenerateWithSeed()
{
int seed = 12345;
// First generation
var image1 = await imageClient.GenerateImageAsync(
prompt: "a red dragon",
size: "1024x1024",
seed: seed,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
// Generate again with same seed
var image2 = await imageClient.GenerateImageAsync(
prompt: "a red dragon",
size: "1024x1024",
seed: seed,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
// image1 and image2 should be very similar
}
public async UniTask GenerateRandomImages()
{
// Passing null seed generates random images
var randomImage = await imageClient.GenerateImageAsync(
prompt: "a blue crystal",
size: "1024x1024",
seed: null, // Random
cancellationToken: this.GetCancellationTokenOnDestroy()
);
}
}Image Conversion
The SDK provides multiple ways to convert and use generated images.
Convert to Texture2D
PlayKit_GeneratedImage generatedImage = await imageClient.GenerateImageAsync(/*...*/);
if (generatedImage != null)
{
// Convert to Texture2D
Texture2D texture = generatedImage.ToTexture2D();
// Use the texture
GetComponent<Renderer>().material.mainTexture = texture;
}Convert to Sprite
PlayKit_GeneratedImage generatedImage = await imageClient.GenerateImageAsync(/*...*/);
if (generatedImage != null)
{
// Convert to Sprite
Sprite sprite = generatedImage.ToSprite();
// Display in UI
GetComponent<Image>().sprite = sprite;
}Using Static Conversion Methods
If you already have a Base64 string, use the static methods:
// Convert Base64 to Texture2D
Texture2D texture = PlayKit_AIImageClient.Base64ToTexture2D(base64String);
// Convert Texture2D to Sprite
Sprite sprite = PlayKit_AIImageClient.Texture2DToSprite(texture);Save Generated Images
Save generated images to disk:
using System.IO;
public class ImageSaver : MonoBehaviour
{
public async UniTask GenerateAndSaveImage(string prompt, string filename)
{
var imageClient = PlayKitSDK.Factory.CreateImageClient();
var result = await imageClient.GenerateImageAsync(
prompt: prompt,
size: "1024x1024",
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
Texture2D texture = result.ToTexture2D();
// Encode texture to PNG
byte[] bytes = texture.EncodeToPNG();
// Save to file
string path = Path.Combine(Application.persistentDataPath, filename);
File.WriteAllBytes(path, bytes);
Debug.Log($"Image saved to: {path}");
}
}
}Prompt Optimization
AI models may optimize your prompts for better results. You can view the original and revised prompts:
var result = await imageClient.GenerateImageAsync(
prompt: "dragon",
size: "1024x1024",
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
Debug.Log($"Your prompt: {result.OriginalPrompt}");
Debug.Log($"AI optimized: {result.RevisedPrompt}");
// Possible output:
// Your prompt: dragon
// AI optimized: A majestic red dragon with scales gleaming in the sunlight,
// perched on a mountain peak, digital art, highly detailed
}Practical Examples
Character Portrait Generator
public class CharacterPortraitGenerator : MonoBehaviour
{
[SerializeField] private Image portraitImage;
private PlayKit_AIImageClient imageClient;
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
}
public async UniTask GenerateCharacterPortrait(
string race,
string characterClass,
string gender
)
{
string prompt = $"fantasy {race} {characterClass} character portrait, " +
$"{gender}, detailed face, professional digital art, " +
$"heroic pose, dramatic lighting";
Debug.Log($"Generating portrait: {prompt}");
var result = await imageClient.GenerateImageAsync(
prompt: prompt,
size: "512x512",
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
portraitImage.sprite = result.ToSprite();
Debug.Log("Portrait generated successfully");
}
}
}
// Usage examples
// await GenerateCharacterPortrait("elf", "mage", "female");
// await GenerateCharacterPortrait("dwarf", "warrior", "male");Item Icon Generator
public class ItemIconGenerator : MonoBehaviour
{
private PlayKit_AIImageClient imageClient;
private Dictionary<string, Sprite> iconCache = new Dictionary<string, Sprite>();
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
}
public async UniTask<Sprite> GetOrGenerateIcon(string itemName, string itemType)
{
// Check cache
string cacheKey = $"{itemName}_{itemType}";
if (iconCache.ContainsKey(cacheKey))
{
return iconCache[cacheKey];
}
// Generate new icon
string prompt = $"{itemName}, {itemType}, game item icon, " +
$"clean background, detailed, high quality, centered";
var result = await imageClient.GenerateImageAsync(
prompt: prompt,
size: "256x256",
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
Sprite icon = result.ToSprite();
iconCache[cacheKey] = icon;
return icon;
}
return null;
}
}Scene Background Generator
public class SceneBackgroundGenerator : MonoBehaviour
{
[SerializeField] private Image backgroundImage;
private PlayKit_AIImageClient imageClient;
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
}
public async UniTask GenerateSceneBackground(string sceneName, string mood)
{
string prompt = $"{sceneName} scene, {mood} atmosphere, " +
$"wide angle, cinematic, detailed environment art, " +
$"no characters";
var result = await imageClient.GenerateImageAsync(
prompt: prompt,
size: "1792x1024", // Widescreen
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
backgroundImage.sprite = result.ToSprite();
}
}
}
// Usage examples
// await GenerateSceneBackground("ancient temple ruins", "mysterious and foggy");
// await GenerateSceneBackground("bustling medieval market", "bright and cheerful");Performance Optimization
Show Loading State
Image generation takes time - show loading state to users:
public class ImageGenerationWithLoading : MonoBehaviour
{
[SerializeField] private Image resultImage;
[SerializeField] private GameObject loadingPanel;
[SerializeField] private Text loadingText;
private PlayKit_AIImageClient imageClient;
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
}
public async UniTask GenerateWithLoading(string prompt)
{
// Show loading UI
loadingPanel.SetActive(true);
loadingText.text = "Generating image...";
try
{
var result = await imageClient.GenerateImageAsync(
prompt: prompt,
size: "1024x1024",
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
resultImage.sprite = result.ToSprite();
loadingText.text = "Generation complete!";
await UniTask.Delay(1000);
}
else
{
loadingText.text = "Generation failed";
await UniTask.Delay(2000);
}
}
catch (System.Exception ex)
{
loadingText.text = $"Error: {ex.Message}";
await UniTask.Delay(2000);
}
finally
{
// Hide loading UI
loadingPanel.SetActive(false);
}
}
}Cache Generated Images
Avoid regenerating the same images:
public class ImageCache : MonoBehaviour
{
private Dictionary<string, Sprite> cache = new Dictionary<string, Sprite>();
private PlayKit_AIImageClient imageClient;
void Start()
{
imageClient = PlayKitSDK.Factory.CreateImageClient();
}
public async UniTask<Sprite> GetOrGenerateImage(string prompt, int? seed = null)
{
// Create cache key
string cacheKey = $"{prompt}_{seed?.ToString() ?? "random"}";
// Check cache
if (cache.ContainsKey(cacheKey))
{
Debug.Log("Returning image from cache");
return cache[cacheKey];
}
// Generate new image
Debug.Log("Generating new image");
var result = await imageClient.GenerateImageAsync(
prompt: prompt,
size: "1024x1024",
seed: seed,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
Sprite sprite = result.ToSprite();
cache[cacheKey] = sprite;
return sprite;
}
return null;
}
public void ClearCache()
{
cache.Clear();
Debug.Log("Image cache cleared");
}
}Error Handling
public async UniTask GenerateImageSafely(string prompt)
{
var imageClient = PlayKitSDK.Factory.CreateImageClient();
try
{
var result = await imageClient.GenerateImageAsync(
prompt: prompt,
size: "1024x1024",
seed: null,
cancellationToken: this.GetCancellationTokenOnDestroy()
);
if (result != null)
{
Sprite sprite = result.ToSprite();
// Use image
}
else
{
Debug.LogError("Image generation returned null");
ShowErrorMessage("Image generation failed, please try again");
}
}
catch (PlayKitImageSizeValidationException ex)
{
Debug.LogError($"Invalid image size: {ex.Message}");
ShowErrorMessage("Please use a valid image size");
}
catch (System.Exception ex)
{
Debug.LogError($"Error generating image: {ex.Message}");
ShowErrorMessage("Generation failed, please check network connection");
}
}
void ShowErrorMessage(string message)
{
// Show error message to user
}Prompt Best Practices
Effective Prompt Structure
// Good prompt: specific, descriptive
string goodPrompt = "a wise old wizard with a long white beard, " +
"wearing blue robes with star patterns, " +
"holding a glowing staff, " +
"fantasy art, detailed, dramatic lighting";
// Okay prompt: too simple
string okayPrompt = "wizard";
// Bad prompt: vague, contradictory
string badPrompt = "wizard that is also a robot and a tree";Prompt Templates for Different Types
public class PromptTemplates
{
public static string CharacterPortrait(string description)
{
return $"{description}, character portrait, " +
$"detailed face, professional digital art, " +
$"front view, neutral background";
}
public static string ItemIcon(string itemName, string itemType)
{
return $"{itemName}, {itemType}, game item icon, " +
$"clean background, centered, detailed, high quality";
}
public static string Environment(string location, string mood)
{
return $"{location}, {mood} atmosphere, " +
$"detailed environment art, wide angle, cinematic";
}
public static string Texture(string material, string pattern)
{
return $"{material} texture, {pattern}, " +
$"seamless, tileable, high resolution, pbr";
}
}Best Practices
- Use specific prompts: Describe in detail what you want
- Add art style: Specify style (e.g., "digital art", "oil painting")
- Show loading state: Image generation takes time, show progress to users
- Cache images: Avoid regenerating the same images
- Choose appropriate sizes: Select image size based on use case - smaller images generate faster
- Use seed values: Use fixed seeds when reproducible results are needed
- Error handling: Always handle possible error cases
- Optimize memory: Release unused Texture2D objects promptly
Next Steps
- Learn about Speech Recognition for voice interaction
- Read the API Reference for complete API documentation