Appearance
Appearance
SupportedLogicVersions
********when releasing the first game update that includes R12.**EntityActor
message handling methods are now marked with various attributes instead of using magic names to identify the handlers. This makes the usage more explicit (and less prone to errors) as well as improves debuggability as the different handlers are now easy to identify in any stack traces, based on the method names alone. The old special method names are not allowed to avoid accidentally relying on them (the methods would not do anything anymore). [CommandHandler]
replaces the old HandleCommand()
[MessageHandler]
replaces the old HandleMessage()
[EntityAskHandler]
replaces the old HandleEntityAsk()
[EntitySynchronizeHandler]
replaces the old HandleEntitySynchronize()
[PubSubMessageHandler]
replaces the old HandlePubSubMessage()
PlayerEventBase
instead of PlayerEventLogEntryPayload
, and the event types need to have the [AnalyticsEvent(...)]
attribute.EventTitle
property has been removed. By default, the name of the event class is used to determine the title, but to use a custom title, the displayName
parameter can be given to the AnalyticsEvent
.playerModel.EventStream.Event(...)
instead of playerModel.ServerListener.OnLoggableEvent(...)
.[MetaImplicitMembersRange]
and [MetaImplicitMembersDefaultRangeForMostDerivedClass]
attributes are required on ImplicitMembers
-flagged serializable base classes. See the section [MetaSerializable] Attribute in Deep Dive: Data Serialization for more information. ImplicitMembers
.pager_targets
map are now pagerduty_alertmanager_key
, pagerduty_cloudwatch_key
, opsgenie_alertmanager_key
, and opsgenie_cloudwatch_key
. All other PagerDuty and Opsgenie keys in configurations have been deprecated. _alertmanager_
keys are used to configure Prometheus AlertManager and the _cloudwatch_
keys are used for AWS CloudWatch Alarm configurations. These are separated as the paging system side configurations are often different (e.g. PagerDuty requires the integration to be specifically of type CloudWatch for CloudWatch integrations, whereas Prometheus AlertManager integrates through a more generic integration point).GameDatabase
class, and all Metaplay query code is in MetaDatabase
class. The SDK database queries can now be performed with MetaDatabase.Get().SomeQueryAsync()
and game-specific queries with GameDatabase.Get().SomeCustomQuery()
. CloudCore
and Game.Server
project sources have been split to Metaplay/
for Metaplay SDK source files and Game/
for any game-specific source files, improving the core vs userland separation.game_specific
folder by the same component file name. Integration hooks for existing components provided through the new integration api. Customization documentation here: Customizing the LiveOps Dashboard FrontendMetaDatabase.Get(QueryPriority.Xyz)
. For any expensive or long-running queries, QueryPriority.Low
should be used.MainGameConfigBuilder
class has been introduced, which takes care of building and creating a binary archive of MainGameConfig
. This clarifies the separation of the offline build step and the runtime loading (from binary archive). The class and the related GameConfigBuilderServices
class are both userland classes and can be modified according to the game's needs.GameConfigBuilder
MonoBehaviour / prefab). This significantly simplifies the implementation and usage of the feature.GoogleSheetFetcher
now uses more efficient batch fetching of multiple sheets in a single operation. Use batch fetching in the example project. The fetcher (including the related DLLs) now lives under Editor/
, so it doesn't get included in the builds.IOnDeserialized
interface has been replaced by a [MetaOnDeserialized]
attribute that can be used on methods of a serializable type. The new attribute works also on nested objects, unlike IOnDeserialized
which was only called for the top-level deserialized object.[MetaOnMemberDeserializationFailure]
attribute allows handling deserialization failures of individual members. This enables player and guild event logs to tolerate the removal or a backwards-incompatible change of an event type while still leaving the player or guild entity otherwise usable.Random Players
and Random Guilds
lists that were shown on the Players
and Guilds
Dashboard pages are now hidden behind the "Developer Mode" toggle - they were not particularly useful or interesting to non-developers.StringId
interning code has been optimized to not allocate any memory for already-interned values: previously unnecessary memory allocations happened during the interning.GameOnSessionStarted
method has been added to PlayerModel
. This method is invoked when a player logs in and starts a session, as opposed to the existing GameOnRestoredFromPersistedState
method (previously called GameOnStateRestored
) which is called whenever the PlayerActor
is woken up for any reason (including due to access from the LiveOps Dashboard).Broadcasts and Push Notifications dashboard pages have been re-worked to make them more consistent and easier to use.
More tooltips on various times and durations all over the LiveOps Dashboard to avoid doing mental math!
Player's login history now includes their locations if you have IP Geolocation enabled.
)
Broadcast Log on the Dashboard's Player Details page shows which broadcasts a player has or has not received.
Infrastructure and Helm chart compatibilities for this release:
infra-modules
version 0.1.2 or later for infrastructuremetaplay-gameserver
Helm chart version 0.2.0 or later for deploymentinfra-modules
version 0.1.4 or later for infrastructuremetaplay-gameserver
Helm chart version 0.2.2 or later for deployment[MetaOnMemberDeserializationFailure]
attribute for member-level deserialization failure handling.MetaplaySDK.RunOnUnityThreadAsync
for deferring Func<>
s to Unity thread.MetaplaySDK.LocalizationManager
to manage OTA updates to localization files.MetaplaySDK
in the running editor to observe guild state.meta-time
component that replaces the previous time-ago
and duration
components.ConfigParser.RegisterParseFunc
is now private. Config library reference id parsers are registered automatically. Custom config parsers must be now be registered in CustomConfigParsers.RegisterCustomParsers (called from LogicInit) with ConfigParser.RegisterCustomParseFunc
.Global
singleton registry class, along with all usage of it.[CommandHandler]
, [MessageHandler]
, [EntityAskHandler]
, [EntitySynchronizeHandler]
, [PubSubMessageHandler]
. These replace the old magic-named methods HandleCommand()
, HandleMessage()
, etc. The magic-named methods are no longer allowed (to avoid accidentally relying on it).GetAll
method in GameConfigLibrary<TKey, TInfo>
(for IGameConfigLibrary
) with an EnumerateAll
method that doesn't construct a new collection, and a GetInfoByKey
method for getting a single item.PlayerModelBase.PlayerId
to make it predictably available.IOnDeserialized
interface with a [MetaOnDeserialized]
attribute for methods, which supports on-deserialization hooks also for nested objects instead of only the top-level deserialized object.MetaSerializableFlags.ImplicitMembers
, a [MetaImplicitMembersRange(start, end)]
is now required on base classes with data members. It is optional on the ultimate concrete class, but if omitted, [MetaImplicitMembersDefaultRangeForMostDerivedClass(start, end)]
must be present on a base class or interface. The purpose of these range allocations is to allow adding members to base classes without changing the implicitly-tagged members on derived classes.[IgnoreDataMember]
in any step of the ancestor chain.[Sensitive]
fields, not just strings.PlayerModel
. Remove PlayerAvatar
: move player profile info into PlayerModel
and resources into PlayerWalletModel
.navigation.js
.ClusterConfig.GetNodeShardIds()
which caused some node loss to not properly trigger Entity subscription loss events with some cluster topologies.