Migrate from v3.x to v6.0.0
BlueStack Unity SDK v6.0.0 is a major release. The native dependencies have moved to the v6 generation of the BlueStack Core SDK, and a number of public C# APIs have been renamed or have shape changes for naming consistency across ad formats.
This guide walks you through the changes you will need to apply to an existing v3.x integration to make it compile and run on v6.0.0.
Full per-version notes live in the Release Notes. This page focuses on the mechanical changes a v3.x consumer needs to make.
At a glance
| Area | What changed | Required action |
|---|---|---|
| Package version | com.azerion.bluestack bumped to 6.0.0 | Update Packages/manifest.json |
| Native dependencies | Core SDK + mediation adapters bumped to v6.0.x | Force-resolve EDM4U (Android) and run pod install (iOS) after upgrade |
BlueStackAds.Initialize | Signature simplified; Settings and split init callbacks removed | Switch to SetDebugMode(bool) + single-callback Initialize |
RewardedVideoAd | Class renamed to RewardedAd | Rename class references |
| Reward event | OnUserRewardEarned → OnAdRewardEarned | Rename subscription |
| Banner events | Renamed to the unified OnAd* convention | Rename subscriptions (see table) |
Banner OnAdLoaded payload | Now carries PreferredBannerSize | Update handler signature |
| Interstitial events | Renamed to the unified OnAd* convention | Rename subscriptions (see table) |
| Rewarded events | Renamed to the unified OnAd* convention | Rename subscriptions (see table) |
BannerAd construction | AdSize is now a mandatory constructor parameter | Pass AdSize to the constructor |
BannerAd.Load | No longer accepts AdSize — it moved to the constructor | Replace Load(adSize) with Load(), and Load(adSize, preference) with Load(requestOptions) |
Preference → RequestOptions | Replaced and made immutable; mutable setters replaced by constructor args | Construct via new RequestOptions(...) with named args; remove Destroy() calls |
Location modernization | Get-only properties + ctor injection; getProvider() → Provider | Build via new Location(lat, lng, provider); read loc.Provider |
Step 1 : Bump the package version
Update Packages/manifest.json:
{
"dependencies": {
"com.azerion.bluestack": "6.0.0"
}
}
After Unity refreshes the package, force-resolve native dependencies:
- Android
- iOS
Assets > External Dependency Manager > Android Resolver > Force Resolve
The resolved AAR dependency line in Assets/Plugins/Android/mainTemplate.gradle should now read:
implementation 'com.azerion:bluestack-sdk-core:6.0.7'
After the next Unity iOS export, run pod install --repo-update in the exported Xcode project to
pull the new BlueStack-SDK v6 pod and mediation adapters.
Step 2 : Update SDK initialization
The v3.x Initialize carried a Settings snapshot and two separate callbacks
(SDKInitializationStatus, AdaptersInitializationStatus). In v6.0.0 the Settings argument is gone,
the debug-mode toggle has its own setter, and a single Initialize callback delivers the
per-adapter InitializationStatus.
Before (v3.x)
using Azerion.BlueStack.API;
public class BlueStackAdController : MonoBehaviour
{
public void Start()
{
Settings settings = new Settings(isDebugModeEnabled: true);
BlueStackAds.Initialize(appId, settings,
HandleSDKInitCompleteAction,
HandleAdaptersInitCompleteAction);
}
private void HandleSDKInitCompleteAction(SDKInitializationStatus sdkInitializationStatus)
{
Debug.Log("SDK init: " + sdkInitializationStatus.IsSuccess);
}
private void HandleAdaptersInitCompleteAction(AdaptersInitializationStatus adaptersStatus)
{
foreach (var kv in adaptersStatus.GetAdapterStatusMap())
{
Debug.Log($"Adapter {kv.Key}: {kv.Value.InitializationState}");
}
}
}
After (v6.0.0)
using Azerion.BlueStack.API;
public class BlueStackAdController : MonoBehaviour
{
public void Start()
{
// Toggle native SDK debug logging at any time.
BlueStackAds.SetDebugMode(true);
BlueStackAds.Initialize(appId, HandleInitializationComplete);
}
// Single callback. Runs on the Unity main thread on both iOS and Android in v6.0.0.
private void HandleInitializationComplete(InitializationStatus status)
{
foreach (var kv in status.AdapterStatusMap)
{
Debug.Log($"Adapter {kv.Key}: {kv.Value.InitializationState} ({kv.Value.Description})");
}
// Readiness can now also be checked synchronously at any time:
if (BlueStackAds.IsInitialized)
{
Debug.Log("BlueStack SDK is ready to load ads.");
}
}
}
Notes:
Settingsis gone — the class is retained for source compatibility only and is no longer consulted by the SDK. Delete anynew Settings(...)constructions in your code.- No more "SDK init success/fail" event — if you previously branched on
SDKInitializationStatus.IsSuccess, instead inspectstatus.AdapterStatusMapto check which adapters reachedAdapterState.Ready. - Main-thread guarantee — v6.0.0 dispatches the init callback to Unity's main thread on both iOS and Android.
Step 3 : Rename RewardedVideoAd to RewardedAd
The class was renamed, the file name in your project also changes (you reference it as RewardedAd everywhere now).
Before
private RewardedVideoAd _rewardedVideoAd;
_rewardedVideoAd = new RewardedVideoAd(placementId);
_rewardedVideoAd.OnUserRewardEarned += (sender, item) =>
{
Debug.Log($"Reward: {item.Amount} {item.Type}");
};
_rewardedVideoAd.Load();
After
private RewardedAd _rewardedAd;
_rewardedAd = new RewardedAd(placementId);
_rewardedAd.OnAdRewardEarned += (sender, item) =>
{
Debug.Log($"Reward: {item.Amount} {item.Type}");
};
_rewardedAd.Load();
Step 4 : Rename ad events
Events on all three full-screen formats now follow the unified OnAdXxx convention.
Banner
| v3.x | v6.0.0 | Payload |
|---|---|---|
OnBannerDidLoad | OnAdLoaded | PreferredBannerSize (was EventArgs) |
OnBannerDidFailed | OnAdFailedToLoad | BlueStackError |
OnBannerDisplay | OnAdDisplayed | EventArgs |
OnBannerHide | OnAdHidden | EventArgs |
OnAdClicked | OnAdClicked | EventArgs |
OnBannerDidRefresh | OnAdRefreshed | EventArgs |
OnBannerDidFailToRefresh | OnAdFailedToRefresh | BlueStackError |
| (new) | OnAdResized | PreferredBannerSize |
The OnAdLoaded payload type changed, your handler now receives the SDK-preferred banner size:
// v3.x
_bannerAd.OnBannerDidLoad += (sender, args) =>
{
_bannerAd.Show();
};
// v6.0.0
_bannerAd.OnAdLoaded += (sender, size) =>
{
Debug.Log($"Loaded banner preferred size: {size.Width}x{size.Height}");
_bannerAd.Show();
};
The new OnAdResized event lets you react when a refresh delivers a creative of a different size:
_bannerAd.OnAdResized += (sender, size) =>
{
Debug.Log($"Banner resized: {size.Width}x{size.Height}");
};
Interstitial
| v3.x | v6.0.0 | Payload |
|---|---|---|
OnInterstitialDidLoaded | OnAdLoaded | EventArgs |
OnInterstitialDidFail | OnAdFailedToLoad | BlueStackError |
OnInterstitialClicked | OnAdClicked | EventArgs |
OnInterstitialDidShown | OnAdDisplayed | EventArgs |
OnInterstitialDisappear | OnAdDismissed | EventArgs |
| (new) | OnAdFailedToDisplay | BlueStackError |
Rewarded
| v3.x | v6.0.0 | Payload |
|---|---|---|
OnRewardedVideoAdLoaded | OnAdLoaded | EventArgs |
OnRewardedVideoAdError | OnAdFailedToLoad | BlueStackError |
OnRewardedVideoAdAppeared | OnAdDisplayed | EventArgs |
OnRewardedVideoAdClicked | OnAdClicked | EventArgs |
OnRewardedVideoAdClosed | OnAdDismissed | EventArgs |
OnUserRewardEarned | OnAdRewardEarned | RewardedItem |
| (new) | OnAdFailedToDisplay | BlueStackError |
A project-wide find-and-replace covers most of the work, the unified OnAd* names do not collide
between formats since each handler is bound to a specific ad instance.
Step 5 : Move AdSize to the BannerAd constructor
In v3.x, AdSize was supplied at load time. In v6.0.0 it is a mandatory constructor parameter,
and Load no longer accepts one. The ad size is fixed for the lifetime of the BannerAd.
Before (v3.x)
_bannerAd = new BannerAd(placementId, AdPosition.Bottom);
_bannerAd.Load(AdSize.Banner);
// With targeting preferences:
_bannerAd.Load(AdSize.Banner, preference);
After (v6.0.0)
_bannerAd = new BannerAd(placementId, AdSize.Banner, AdPosition.Bottom);
_bannerAd.Load();
// With targeting (see Step 6):
_bannerAd.Load(requestOptions);
v6.0.0 also introduces two new banner constructors, screen-space (Vector2) and
anchor (Transform) positioning. They aren't part of the migration,
but see New banner positioning constructors
below if you want to adopt them.
Step 6 : Replace Preference with RequestOptions
In v3.x, ad targeting was set via a mutable Preference builder with Set* methods, then passed
to Load(...). In v6.0.0 the class is replaced with immutable RequestOptions, all fields are set in a single constructor call.
Before (v3.x)
Preference preference = new Preference();
Location myLocation = new Location(Location.NONE_PROVIDER)
{
Latitude = 35.757866,
Longitude = 10.810547
};
preference.SetAge(25);
preference.SetGender(Gender.Male);
preference.SetLocation(myLocation, 1);
preference.SetLanguage("en");
preference.SetKeyword("brand=myBrand;category=sport");
preference.SetContentUrl("https://example.com");
_bannerAd.Load(preference);
// …
preference.Destroy();
After (v6.0.0)
var requestOptions = new RequestOptions(
age: 25,
gender: Gender.Male,
location: new Location(35.757866, 10.810547, Location.GPS_PROVIDER),
consentFlag: 1,
language: "en",
keyword: "brand=myBrand;category=sport",
contentUrl: "https://example.com");
_bannerAd.Load(requestOptions);
_interstitialAd.Load(requestOptions);
_rewardedAd.Load(requestOptions);
// No Destroy() needed — RequestOptions holds no native resources on the Unity side.
A few notes:
- All
RequestOptionsconstructor parameters are optional, omit any field you don't want to send. Locationis also now immutable. Passlatitudeandlongitudeto its constructor instead of setting them as properties, and read the provider via theProviderproperty (the oldgetProvider()method is gone).- A single
RequestOptionsinstance can be safely reused across multipleLoadcalls. Destroy()is gone. There's no native handle held on the Unity side.
See Targeting Audiences for the full reference.
Step 7 : Verify the build
- Editor: re-open the project. Compilation errors will surface every remaining v3.x identifier; work through them top-down.
- Android: build a debug APK. Force-resolve Android dependencies first
(
Assets > External Dependency Manager > Android Resolver > Force Resolve). - iOS: export the Xcode project. Delete the
Pods/andPodfile.lockfrom previous v3.x exports if present, then runpod install --repo-update.
After a v3.x → v6.0.0 upgrade, do a clean build of the player. Stale managed assemblies referencing the old class / event names can mask compilation errors until they're flushed.
Recommended v6.0.0 features to adopt
These additions are optional but generally simplify common integrations.
IsReady for full-screen ads
Both InterstitialAd and RewardedAd expose an IsReady property:
if (_interstitialAd.IsReady) _interstitialAd.Show();
if (_rewardedAd.IsReady) _rewardedAd.Show();
This lets you gate Show() from a button click without having to wire up OnAdLoaded callback
state-tracking yourself.
New banner positioning constructors
v6.0.0 adds two banner constructors that did not exist in v3.x (which supported only AdPosition
Top/Bottom placement):
// Screen-space position — (x, y) is the banner's TOP-LEFT corner, in Unity pixels (bottom-left origin).
_bannerAd = new BannerAd(placementId, AdSize.Banner, new Vector2(x, y));
// GameObject anchor — the banner follows anchor.position (its TOP-LEFT corner) automatically via the
// AdPlacementHandler component the SDK attaches.
_bannerAd = new BannerAd(placementId, AdSize.Banner, anchorTransform, trackingCamera);
For both constructors the supplied point is the banner's top-left corner; the banner extends right and downward from it, matching native iOS / Android frame placement. Custom-positioned banners always ignore the device safe area.
For the anchor constructor, throttle tracking when the anchor moves every frame:
_bannerAd.PlacementHandler.UpdateInterval = 0.1f; // clamped to [0, 5] seconds; default: every frame
useSafeArea opt-out
For sticky Top/Bottom banners, pass useSafeArea: false to overlap the notch / home indicator /
status bar:
_bannerAd = new BannerAd(placementId, AdSize.Banner, AdPosition.Bottom, useSafeArea: false);
Custom-positioned banners (Vector2 or Transform anchor) always ignore the safe area regardless
of this flag.
Banner masking
v6.0.0 adds banner masking, clip a banner to a UI RectTransform region.
The mask follows the RectTransform as it animates or resizes:
_bannerAd.SetMask(maskRect); // clip the banner to the RectTransform region
_bannerAd.RemoveMask(); // stop clipping
// If the mask is bound to a heavily animated RectTransform, throttle native updates:
_bannerAd.MaskHandler.UpdateInterval = 0.1f; // 10 Hz; clamped to [0, 5] seconds
See Banner masking for the full reference.
Removed APIs reference
If you see compile errors for any of the following symbols, refer to the section linked alongside.
| Removed | Replacement | Section |
|---|---|---|
Settings(bool) argument to Initialize | BlueStackAds.SetDebugMode(bool) | Step 2 |
Action<SDKInitializationStatus> init callback | Action<InitializationStatus> (single callback) | Step 2 |
Action<IInitializationStatusClient> adapters callback | Folded into the single Action<InitializationStatus> | Step 2 |
class RewardedVideoAd | class RewardedAd | Step 3 |
RewardedAd.OnUserRewardEarned | RewardedAd.OnAdRewardEarned | Step 3 |
BannerAd.OnBannerDidLoad and family | BannerAd.OnAd* | Step 4 — Banner |
InterstitialAd.OnInterstitial* | InterstitialAd.OnAd* | Step 4 — Interstitial |
RewardedAd.OnRewardedVideoAd* | RewardedAd.OnAd* | Step 4 — Rewarded |
BannerAd.Load(AdSize) / Load(AdSize, Preference) | BannerAd.Load() / Load(RequestOptions); AdSize is now a constructor parameter | Step 5 |
class Preference and its Set* setter methods | class RequestOptions (immutable, constructor-injected) | Step 6 |
Preference.Destroy() | Removed, no native handle on the Unity side | Step 6 |
Location mutable setters / getProvider() | Immutable new Location(lat, lng, provider) + Provider property | Step 6 |