Custom Assets can't use inherited types as parameters.
Is your feature request related to a problem? Please describe.
I was trying to use a custom asset that used a base type called BaseItem as the parameter but it threw errors on compilation.
Describe the solution you'd like It would be a massive time saver to remove the boilerplate of creating individual items when the base type could be used. Below is what I was trying to do:
[DataContract]
[AssetDescription(FileExtension, AllowArchetype = false)]
[AssetContentType(typeof(ResourceItem))]
[AssetFormatVersion(nameof(Definitiions), CurrentVersion, "1.0.0.0")]
public class ResourceItemAsset : Asset
{
private const string CurrentVersion = "1.0.0.0";
public const string FileExtension = $".{nameof(ResourceItem)}";
public BaseItem Item { get; set; }
}
/// <summary> Compiler which transforms your <see cref="ResourceItemAsset"/> into <see cref="ResourceItem"/> when building your game </summary>
[AssetCompiler(typeof(ResourceItemAsset), typeof(AssetCompilationContext))]
public sealed class ResourceItemCompiler : AssetCompilerBase
{
protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
{
var asset = (ResourceItemAsset)assetItem.Asset;
// you can have many build steps, each one is running an AssetCommand
result.BuildSteps = new AssetBuildStep(assetItem);
result.BuildSteps.Add(new ResourceItemDesignToRuntimeCommand(targetUrlInStorage, asset, assetItem.Package));
}
/// <summary>
/// An <see cref="AssetCommand"/> that converts design time asset into runtime asset.
/// </summary>
public class ResourceItemDesignToRuntimeCommand(string url, ResourceItemAsset parameters, IAssetFinder assetFinder)
: AssetCommand<ResourceItemAsset>(url, parameters, assetFinder)
{
protected override Task<ResultStatus> DoCommandOverride(ICommandContext commandContext)
{
var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);
assetManager.Save(Url, Parameters.Item);
commandContext.Logger.Info($"Saved {nameof(ResourceItem)}: {Url}");
return Task.FromResult(ResultStatus.Successful);
}
}
}
BaseType:
[DataContract(Inherited = true)]
public abstract class BaseItem
{
/// <summary>
/// The unique identifier for the item.
/// </summary>
[DataMemberIgnore]
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// The Name for the item.
/// </summary>
public string Name { get; set; }
/// <summary>
/// The description of the item.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Used to determine the base trading value of an item.
/// </summary>
public int Value { get; set; }
/// <summary>
/// The weight of the item, used for inventory management and affecting the movement stats of the holder.
/// </summary>
public int Weight { get; set; }
}
One of the inheritted types:
[ContentSerializer(typeof(DataContentSerializerWithReuse<ConsumableItem>))]
[ReferenceSerializer, DataSerializerGlobal(typeof(ReferenceSerializer<ConsumableItem>), Profile = "Content")]
public class ConsumableItem : BaseItem
{
}
Describe alternatives you've considered The alternative is just to create an asset for each individual Item type.
Additional context This architecture works within a Component type in a scene of GameStudio but the AssetCompiler seem to be the blocker for here for custom assets.
What is the compilation error?
So I tried to recreate a example project and now I'm getting the error in GameStudio directly as a template error.
Error: Failed to create new asset from template.
InvalidOperationException: Error when serializing reference.
at Stride.Core.Serialization.Contents.ReferenceSerializer`1.Serialize(T& obj, ArchiveMode mode, SerializationStream stream) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\core\Stride.Core.Serialization\Serialization\Contents\ReferenceSerializer.cs:line 86
at Stride.Core.Serialization.MemberReuseSerializer`1.Serialize(T& obj, ArchiveMode mode, SerializationStream stream) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\core\Stride.Core\Serialization\MemberSerializerGenerated.cs:line 1225
at Stride.Core.DataSerializers.MyGame10AssetsDefinitions_GameItemAssetSerializer.Serialize(GameItemAsset& obj, ArchiveMode mode, SerializationStream stream)
at Stride.Core.Serialization.DataSerializer`1.Serialize(Object& obj, ArchiveMode mode, SerializationStream stream) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\core\Stride.Core\Serialization\DataSerializer.cs:line 80
at Stride.Core.Serialization.MemberReuseSerializer`1.SerializeExtended(T& obj, ArchiveMode mode, SerializationStream stream, DataSerializer`1 dataSerializer) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\core\Stride.Core\Serialization\MemberSerializerGenerated.cs:line 1429
at Stride.Core.Assets.AssetCloner..ctor(Object value, AssetClonerFlags flags, IEnumerable`1 externalIdentifiables) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\assets\Stride.Core.Assets\AssetCloner.cs:line 73
at Stride.Core.Assets.AssetCloner.Clone(Object asset, AssetClonerFlags flags, HashSet`1 externalIdentifiable, Dictionary`2& idRemapping) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\assets\Stride.Core.Assets\AssetCloner.cs:line 225
at Stride.Core.Assets.AssetCloner.Clone(Object asset, AssetClonerFlags flags, Dictionary`2& idRemapping) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\assets\Stride.Core.Assets\AssetCloner.cs:line 240
at Stride.Core.Assets.Analysis.AssetDependencyManager.TrackAsset(AssetId assetId) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\assets\Stride.Core.Assets\Analysis\AssetDependencyManager.cs:line 349
at Stride.Core.Assets.Analysis.AssetDependencyManager.TrackAsset(AssetItem assetItemSource) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\assets\Stride.Core.Assets\Analysis\AssetDependencyManager.cs:line 321
at Stride.Core.Assets.Analysis.AssetDependencyManager.Assets_CollectionChanged(Object sender, NotifyCollectionChangedEventArgs e) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\assets\Stride.Core.Assets\Analysis\AssetDependencyManager.cs:line 576
at Stride.Core.Assets.PackageAssetCollection.Add(AssetItem item) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\assets\Stride.Core.Assets\PackageAssetCollection.cs:line 137
at Stride.Assets.Presentation.Templates.AssetTemplateGenerator.Run(AssetTemplateGeneratorParameters parameters) in C:\BuildAgent\work\b5f46e3c4829a09e\sources\editor\Stride.Assets.Presentation\Templates\AssetTemplateGenerator.cs:line 52
I think the original error was happening on build possibly because of an improper clean? I cant seem to get the same error as before but it still does not let me create the asset due to the above.
Project example:
Once you open the GameStudio, you will see the error when adding the asset GameItems->GameItem.
One more thing to add here as I didn't notice it before and its probably relevant. The inheriting types do not serialize the base class properties. I am assuming I either need to make a custom serializer for the type that includes the abstract data or in my case I found an interface to be more useful for what I was doing.