Skip to main content
Version: 6.x.x

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.

info

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​

AreaWhat changedRequired action
Package versioncom.azerion.bluestack bumped to 6.0.0Update Packages/manifest.json
Native dependenciesCore SDK + mediation adapters bumped to v6.0.xForce-resolve EDM4U (Android) and run pod install (iOS) after upgrade
BlueStackAds.InitializeSignature simplified; Settings and split init callbacks removedSwitch to SetDebugMode(bool) + single-callback Initialize
RewardedVideoAdClass renamed to RewardedAdRename class references
Reward eventOnUserRewardEarned → OnAdRewardEarnedRename subscription
Banner eventsRenamed to the unified OnAd* conventionRename subscriptions (see table)
Banner OnAdLoaded payloadNow carries PreferredBannerSizeUpdate handler signature
Interstitial eventsRenamed to the unified OnAd* conventionRename subscriptions (see table)
Rewarded eventsRenamed to the unified OnAd* conventionRename subscriptions (see table)
BannerAd constructionAdSize is now a mandatory constructor parameterPass AdSize to the constructor
BannerAd.LoadNo longer accepts AdSize — it moved to the constructorReplace Load(adSize) with Load(), and Load(adSize, preference) with Load(requestOptions)
Preference → RequestOptionsReplaced and made immutable; mutable setters replaced by constructor argsConstruct via new RequestOptions(...) with named args; remove Destroy() calls
Location modernizationGet-only properties + ctor injection; getProvider() → ProviderBuild 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:

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'

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:

  • Settings is gone — the class is retained for source compatibility only and is no longer consulted by the SDK. Delete any new Settings(...) constructions in your code.
  • No more "SDK init success/fail" event — if you previously branched on SDKInitializationStatus.IsSuccess, instead inspect status.AdapterStatusMap to check which adapters reached AdapterState.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.

v3.xv6.0.0Payload
OnBannerDidLoadOnAdLoadedPreferredBannerSize (was EventArgs)
OnBannerDidFailedOnAdFailedToLoadBlueStackError
OnBannerDisplayOnAdDisplayedEventArgs
OnBannerHideOnAdHiddenEventArgs
OnAdClickedOnAdClickedEventArgs
OnBannerDidRefreshOnAdRefreshedEventArgs
OnBannerDidFailToRefreshOnAdFailedToRefreshBlueStackError
(new)OnAdResizedPreferredBannerSize

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.xv6.0.0Payload
OnInterstitialDidLoadedOnAdLoadedEventArgs
OnInterstitialDidFailOnAdFailedToLoadBlueStackError
OnInterstitialClickedOnAdClickedEventArgs
OnInterstitialDidShownOnAdDisplayedEventArgs
OnInterstitialDisappearOnAdDismissedEventArgs
(new)OnAdFailedToDisplayBlueStackError

Rewarded​

v3.xv6.0.0Payload
OnRewardedVideoAdLoadedOnAdLoadedEventArgs
OnRewardedVideoAdErrorOnAdFailedToLoadBlueStackError
OnRewardedVideoAdAppearedOnAdDisplayedEventArgs
OnRewardedVideoAdClickedOnAdClickedEventArgs
OnRewardedVideoAdClosedOnAdDismissedEventArgs
OnUserRewardEarnedOnAdRewardEarnedRewardedItem
(new)OnAdFailedToDisplayBlueStackError
tip

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);
tip

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 RequestOptions constructor parameters are optional, omit any field you don't want to send.
  • Location is also now immutable. Pass latitude and longitude to its constructor instead of setting them as properties, and read the provider via the Provider property (the old getProvider() method is gone).
  • A single RequestOptions instance can be safely reused across multiple Load calls.
  • 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​

  1. Editor: re-open the project. Compilation errors will surface every remaining v3.x identifier; work through them top-down.
  2. Android: build a debug APK. Force-resolve Android dependencies first (Assets > External Dependency Manager > Android Resolver > Force Resolve).
  3. iOS: export the Xcode project. Delete the Pods/ and Podfile.lock from previous v3.x exports if present, then run pod install --repo-update.
caution

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.


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);
note

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.

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.

RemovedReplacementSection
Settings(bool) argument to InitializeBlueStackAds.SetDebugMode(bool)Step 2
Action<SDKInitializationStatus> init callbackAction<InitializationStatus> (single callback)Step 2
Action<IInitializationStatusClient> adapters callbackFolded into the single Action<InitializationStatus>Step 2
class RewardedVideoAdclass RewardedAdStep 3
RewardedAd.OnUserRewardEarnedRewardedAd.OnAdRewardEarnedStep 3
BannerAd.OnBannerDidLoad and familyBannerAd.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 parameterStep 5
class Preference and its Set* setter methodsclass RequestOptions (immutable, constructor-injected)Step 6
Preference.Destroy()Removed, no native handle on the Unity sideStep 6
Location mutable setters / getProvider()Immutable new Location(lat, lng, provider) + Provider propertyStep 6