Appearance
Appearance
New feature: Leagues is now out of preview. The new leagues release now has full support for player leagues, where players face off against each other in local leaderboards and get rewards and rank-ups based on their performance. Check out the Quickstart Guide to get started.
Major improvement: Upgrade to Vue 3 (compatibility mode) has been rolled out to the LiveOps Dashboard. Vue 3 brings native support for TypeScript, better performance, and a better developer experience for making your own dashboard components. This upgrade also enables you to leverage the growing ecosystem of open-source Vue 3 plugins and components. The upgrade is done in compatibility mode, which means that most Vue 2 code will continue to work. We will continue to upgrade our dashboard components and dependencies to Vue 3 in the coming releases and eventually retire the compatibility mode.
Major improvement: Serialization performance has been improved by up to 3-4x and memory allocations have been significantly reduced. The serializer generation is also significantly faster within Unity.
LogicVersion
and update the game client and server synchronously._node_modules
folder and reinstall dependencies with npm ci
. NPM can get confused with major updates like this.bootstrap-vue
UI component library is not, and will likely never be, compatible with Vue 3 due to the developer community getting disrupted by Russia's invasion of Ukraine. We have implemented workarounds to keep it functional but the intent is to replace it with a Vue 3 compatible library in the future.INFO
Note: If you have a service contract signed with Metaplay, all the breaking changes have been fixed already in the SDK upgrade pull request of your project. Otherwise, please see CHANGELOG.md
for a full list of changes, along with the HelloWorld and Idler samples for references on how to apply the changes.
OverviewView
, GameConfigListView
, GameConfigDetailsView
and GameConfigDiffView
pages.MetaListCard
s. This is useful for example when looking at the global incident reports and you don't want the list refreshing while browsing it.MetaInputSelect
- A dropdown component that supports searching, async options loading, auto-completion, multiple selection, and more.MetaInputPlayerSelect
- A dropdown component for searching and selecting a player.MetaInputGuildSelect
- A dropdown component for searching and selecting a guild.MetaInputDateTime
- A date and time picker component.MetaInputDateTimeRange
- A date and time range (start + end time) picker component.Span<T>
data types. Unity 2021 is required for Span<T>
support and in older Unity versions, the spans are emulated at the cost of some performance. We recommend upgrading to Unity 2021 LTS if performance is of the essence.AssemblyBuilder
. This avoids the cold-start performance hit present when using Roslyn directly.SegmentedIOBuffer
s which themselves recycle the individual memory pages via ArrayPool<T>
.Scripts/integration-tests.py
which are easier to use with various CI systems, including Github Actions and Bitbucket Pipelines. If you'd like to start using them, please talk to us.--Database:SqliteInMemory=true
argument on the command line. The in-memory SQLite is performant enough to allow for thousands of bots locally.METAPLAY_ENABLE_WEBGL
will enable the warnings -- we recommend doing this on all platforms so the warning doesn't go unnoticed. See Metaplay & WebGL for more information.Infrastructure and Helm chart compatibilities for this release:
infra-modules
version 0.2.2 or later for infrastructuremetaplay-gameserver
Helm chart version 0.4.4 or later for deploymentinfra-modules
version 0.2.7 or later for infrastructuremetaplay-gameserver
Helm chart version 0.4.5 or later for deploymentSDK: The MetaplayClient
SDK default integration class is now abstract and integrations should declare a derived class for type-safe access to the current player model.
MetaplayClient
class in the integration that inherits from MetaplayClientBase<TPlayerModel>
, substituting your concrete PlayerModel
class as the template parameter. Reusing the name MetaplayClient
should make the impact on using code minimal. The implementation of the class can be empty, the static MetaplayClient
API methods are preserved in the base class.SDK: ISharedGameConfig
's library accessors have been restructured to require less boilerplate, using an IGameConfigLibrary<,>
interface.
ISharedGameConfig
directly instead of via SharedGameConfigTemplate
or SharedGameConfigBase
, update the library accessors to adhere to the new interface.SDK: The Unity localizations build is now expected to place a single-archive copy of localizations as GameConfig/Localizations.mpa
.
GameConfigBuilder
to build localizations into a single file and use the file when uploading the localizations to the server: const string ServerLocalizationsPath = "Backend/Server/GameConfig/Localizations.mpa";
public static async Task TryBuildLocalizations()
{
// Build Localizations & write each language in its own file
await BuildArchiveAsync(ServerLocalizationsPath,
ArchiveStorageFormat.SingleFile,
() => BuildLocalizationsArchiveAsync(MetaTime.Now),
onSuccessHandler: fullArchive =>
{
// Export Localizations into StreamingAssets/ in FolderEncoding format
Debug.Log($"Writing Localizations archive as multiple files into {ClientLocalizationsPath}");
ConfigArchive.FolderEncoding.WriteToDirectory(fullArchive, ClientLocalizationsPath);
});
}
public static async Task PublishLocalizationsToLocal()
{
ConfigArchive localizationsArchive = await ConfigArchive.FromFileAsync(ServerLocalizationsPath);
await GameConfigBuildUtil.PublishLocalizationArchiveToServerAsync("http://localhost:5550/api/", localizationsArchive, authorizationToken: null, confirmDialog: false);
}
SDK: As the localizations archive is now longer sourced from within the Unity assets folder the server docker build no longer includes the Assets/StreamingAssets/
directory.
Dockerfile.server
to copy them explicitly.SDK: GameConfigBuildUtil.PublishArchiveToServerAsync()
has been replaced with PublishGameConfigArchiveToServerAsync()
and PublishLocalizationArchiveToServerAsync()
.
SDK: SocialAuthenticationClaimGooglePlay
is now SocialAuthenticationClaimGooglePlayV1
to clearly communicate it is the legacy version.
SDK: playerModel.HasMetaOffersToRefresh()
has been replaced with playerModel.GetMetaOfferGroupsRefreshInfo()
which returns a list of refreshable offer groups. This is used to reduce workload on the server by reducing the number of offer groups it needs to consider when refreshing.
HasMetaOffersToRefresh()
, you should now use GetMetaOfferGroupsRefreshInfo()
and call the HasAny()
method on the result, and also pass the result to the PlayerRefreshMetaOffers
action.SDK: To enable WebGL support in the client, it is now required to define the preprocessing symbol METAPLAY_ENABLE_WEBGL
. This also enables warnings about features which are poorly-supported in Unity WebGL builds. See the documentation page Metaplay & WebGL for details.
csc.rsp
in your Assets
folder, with a line saying -define:METAPLAY_ENABLE_WEBGL
.SDK: DatabaseScanJobSpec
's API has been changed: added method ComputeAggregateStatistics
which combines multiple workers' statistics into one, and changed method CreateSummary
to take only one statistics object instead of multiple.
DatabaseScanJobSpec
s to adhere to the new API. Note that you likely already have the necessary code for ComputeAggregateStatistics
in your existing CreateSummary
method, so this is likely a matter or minor refactoring.Dashboard: Major dependency updates with each their own braking changes: Vue 2 -> 3 (compatibility mode), Vue Router 3 -> 4, Vite 3 -> 4, Cypress 11 -> 12. This is a complex update but most of the changes are in the core SDK. We will work with the affected customers to migrate their code as needed.
node_modules
folder and reinstall dependencies with npm ci
. NPM can get confused with major updates like this.Dashboard: Vue 3 compatibility mode has been enabled. This means that Vue 2 and Vue 3 APIs can be used interchangeably, but there are some breaking changes and warnings about deprecated APIs.
Dashboard: Vue 3 has a new component registration API that is incompatible with Vue 2.
app.component()
instead of Vue.component()
.Dashboard: Vue 3 has a new v-model
syntax that is incompatible with Vue 2. The current compatibility mode allows both syntaxes to be used, but this will be removed in a future release.
v-model
property and an input event like @input
or @update
at the same time may have a race condition where the input event is fired before the v-model
is updated. Update your custom dashboard components to use the input event's value instead of the v-model
value to guarantee the updated value is used.Dashboard: Vue 3 has changed the execution order of v-for
and v-if
directives. The official recommendation is to not use v-if
and v-for
on the same element as the order is ambiguous to the reader.
v-if
and v-for
on the same element and instead use v-if
on a child element to make the order explicit.Dashboard: Vue Router v4 now has built-in support for accessing the current route
and router
instances via the useRoute()
and useRouter()
composition APIs. Our previous workaround for this has been removed.
useRoute()
and useRouter()
to import from vue-router
.Dashboard: Vue Router v4 has changed the route props API. Props can now be string[]
in addition to string
.
routeParamToSingleValue()
utility function from the core dashboard module to continue with the old behavior.Dashboard: Vue Router v4 has changed how routes are added to the router. The addNavigationEntry()
integration API has been updated to work with the new router by moving the content of route.meta
parameter into it's own top-level parameter in the addNavigationEntry()
function.
addNavigationEntry()
to use the new, separate route metadata parameter.Dashboard: The displayName
field of GameSpecificReward
was removed because it was obsolete.
addPlayerRewards()
to remove the displayName
field.Dashboard: Cypress 12 has enabled isolated testing by default. This means that each it()
command runs in a separate, clean browser session. This is a breaking change for tests that rely on the old behavior.
{ testIsolation: false }
to incompatible tests or update the tests to run in one it()
command instead of multiple, as needed.Dashboard: Meta-Teleport
component has been removed in favour of a new type-safe API to dynamically update the headerbar title.
useHeaderbar()
composition API of the core dashboard module to update the title.Dashboard: The unit tests are now run explicitly by the Dockerfile.
npm run test:unit
from your Backend/Dashboard/package.json
from the build
command.PlayerSegmentInfoBase.MatchesPlayer
for the ability to customize the player segment matching logic in the integration.--Database:SqliteInMemory=true
option. Useful for benchmarking locally with BotClient.MetaOfferGroupInfoBase.MaxOffersActive
that can be used to limit the number of simultaneously active offers in an offer group.AuthenticationConflictAutoResolver
integration allows customizing social login conflict auto-resolution rules.MetaTask.Run()
allows executing tasks on a chosen Scheduler without the pitfalls of Task.Factory.StartNew()
(no need to call Unwrap()
).MetaTask.UnityMainScheduler
is a convenience getter of the Unity Main thread scheduler. With above MetaTask.Run()
, posting work on the correct thread is easy.MetaTask.BackgroundScheduler
is a convenience getter of the best available background scheduler. On WebGL this is the main thread.Task.GetCompletedResult()
is a convenience helper for Task.Result
which throws (instead of blocking) if Result
is not yet available. Convenient for avoiding accidental deadlocks especially on WebGL.PlayerEventIncidentRecorded
analytics events.Scripts/integration-tests.py
. The old Scripts/tests.py
is now deprecated and will be removed in the future.Backend/
directory to Dockerfile.server
via --build-arg BACKEND_DIR=xyz
to avoid needing to modify the Dockerfile itself when using a custom directory.OverviewView
, GameConfigListView
, GameConfigDetailsView
and GameConfigDiffView
pages. You can now add or remove injected components to these views.MetaInputSelect
- A dropdown component that supports searching, async options loading, auto-completion, multiple selection, and more.MetaInputPlayerSelect
- A dropdown component for searching and selecting a player.MetaInputGuildSelect
- A dropdown component for searching and selecting a guild.MetaInputDateTime
- A date and time picker component.MetaInputDateTimeRange
- A date and time range (start + end time) picker component.Sample-Server.sln
files have been moved to the project Backend/
directory in all sample projects.Assets/SharedCode
is now built into a separate SharedCode
assembly that does not reference the default assemblies or UnityEngine assemblies.MetaplayClient
into MetaplayClientState
accessed via the static accessors in MetaplayClient
.EmptyGameLogic.cs
previously used for providing minimal integration for client project to build.AssemblyBuilder
to compile the generated serializer code. On some machines was measured to be about 4x faster.Temp/Metaplay/
is now used for Unity temporary files instead of MetaplayTemp/
to avoid clutter in the project root.Metaplay.Generated.dll
for improved performance.curl
from the Docker images due to frequent vulnerabilities in the package. Also remove the curl static.gc.apple.com
test in Dockerfile as it's covered by the unit tests.AdminApi:Type = AuthenticationType.Auth0
is deprecated and will be removed in a future release. Use the more general AuthenticationType.JWT
instead.ReadOnlyConfigArchive
.SegmentedIOBuffer
segments and then using recycled buffers in the MetaSerialization
APIs directly. This considerably reduces the number of memory allocations done by the serializers and reduces the amount of memory retained by the various server-side actors.IOWriter
class for improved performance.Span<T>
APIs.GoogleSheets.CredentialsPath
) as AWS secrets manager URL in addition to local file.PlayerActor.OnClientSessionHandshake()
is deprecated in favor of OnClientSessionHandshakeAsync()
.PlayerActor.OnSessionStart()
is deprecated in favor of OnSessionStartAsync()
.EntityActor.CastMessage()
, EntityAskAsync()
, and other messaging functions are now thread-safe also within a single actor and may be used from background threads.LogicVersionMismatch
errors are no longer reported as player incidents. Logic version mismatches are often expected, especially after a server update.RecyclingSerializer
and replace all usage with calls to MetaSerialization
as it now uses recycled buffers internally.MetaplaySDK.DeviceGuid
which is negotiated at session startup and doesn't depend on the DeviceId
authentication method. The legacy per-device book keeping in PlayerModel has been repurposed as DeviceHistory
and additional statistics are tracked per device on login. Existing device identification based on DeviceId
authentication is migrated to the new scheme and partial stats are migrated from recent login history.IAPManager
to support Unity Purchasing 4.6.0 (regarding changes to IStoreListener.OnInitializeFailed()
and IAppleExtensions.RestoreTransactions()
).link.xml
: Metaplay.Unity
and the game-specific shared code assembly. This should avoid issues caused by Unity's code stripping, and reduce the need for explicit [Preserve]
attributes in code.Dockerfile.server
now builds the C# game server before building the dashboard. Dashboard build uses Debian (bullseye-slim) -based base image.Dockerfile.server
now includes BotClient in the built image. In a future release, the BotClient docker images will be replaced with the server image, the ECR repository and Dockerfile.botclient
deprecated and removed.Dockerfile.server
now generates the serializer code by starting the server after the build.CoreUiPlacement
component now forwards all props and listeners to child components. Additionally removed small wrapper components that were used to forward props when using UiPlacements for example for the PlayerAuditLogCard
.Options API
SFC based syntax to the Composition API
Setup based syntax.SIGTERM
handler.IAPManager
's behavior when using Unity's development-mode fake IAP store, which would erroneously cause purchases to be displayed as duplicates in the dashboard.MetaplayConnection
tear down by handling cancel request before any other operations.PlayerChecksumMismatchConnectionError
are now grouped more appropriately in "top incidents" views. This is done by omitting noisy details from the incident's "fingerprint".MetaTime
from a string with a numeric time offset specifier, the offset is now correctly applied, instead of erroneously applying also the server's local time offset.PlayerModel
.MessageAudienceForm
, SegmentsCard
and TargetingCard
.TargetingCard.vue
when a new game config where a target segment has been removed is published.