stride3d / stride3d/stride

Custom Assets can't use inherited types as parameters.

Open
#2,713 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
C#
Stars
7.8k
Forks
1.2k
Avg merge
2d 17h
Merged PRs (30d)
49

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the AssetCompilerBase and AssetCommand path used by ResourceItemAsset, then compare it with the Component serialization behavior that already supports inherited types. Investigate how BaseItem, ConsumableItem, ContentManager, DataContentSerializerWithReuse, and ReferenceSerializer are handled during custom asset compilation. Done means a custom asset parameterized by BaseItem compiles and supports its inherited item types without separate assets.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
game-dev, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.