Search Unity

AddressableAsset, allow developers to force a specific type?

Discussion in 'Addressables' started by Prodigga, Jun 20, 2018.

  1. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Edit: I mean AssetReference, not AddressableAsset

    Hi there

    In the getting started guide, an explosion prefab is spawned using an AssetReference. However, the user can plug in any type of addressable asset here (materials, prefabs, etc), even though the code requires and expects a GameObject.

    This would kind of be like if you could only serialise UnityEngine.Object references in your scripts. The user would be able to plug in any type of object, even though your code would expect something of a specific type.

    Imagine the headache if your code look liked this:

    Code (CSharp):
    1. public Object Explosion; //expecting a GameObject, but no way to enforce it!
    Maybe we could specific the type of asset by inheriting a generic base class: (since this is the only way unity would be able to serialise it)

    Code (CSharp):
    1. [Serializable]
    2. public class GameObjectReference : BaseAssetReference<GameObject>
    And the implementation for the built in type AssetReference would be:

    Code (CSharp):
    1. [Serializable]
    2. public class AssetReference : BaseAssetReference<UnityEngine.Object>
    Ideally you would just be able to add a public property to your object like so:

    Code (CSharp):
    1. public AssetReference<Sprite> mySprite;
    But Unitys serializer doesn't support that, so you'd have to define a new class:

    Code (CSharp):
    1. [Serializable]
    2. public class SpriteReference : BaseAssetReference<Sprite>
    And use that in your scripts:

    Code (CSharp):
    1. public SpriteReference mySprite;
    Less error prone, and also means that when we load the addressable asset, we don't have to make sure we cast it to the right type.

    So no need for:

    Code (CSharp):
    1. mySprite.LoadAsync<Sprite>();
    Since it already knows it's a Sprite.
     
    Last edited: Jun 20, 2018
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,609
    That should be the preferred approach. It would be rather unhandy, if I have to implement a specific class for every asset-type I want to reference. I just thought of the gazillion ScriptableObject types we had in one project, that would be quite a lot custom classes for the references :)
     
    phobos2077 likes this.
  3. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    Thanks to both of you for trying out the system...

    Peter - Yes, AssetReference<Sprite> would be preferred, but it does not work. As Prodigga points out, we can't do that. The serialization system won't allow it (meaning the member won't show up in the inspector window). So we're stuck with the more explicit option.

    Prodigga - While our sample game is just using a blind AssetReference in a very unsafe way, the package itself already has (almost exactly) what you are suggesting. If you look in the package code, in /Runtime/AssetReference.cs, you can see this implemented. We've only created 5 specific classes for now, but they are there. So in one of your classes you should be able to add a AssetReferenceGameObject or any of the others without problem.

    Our sample game is very bare bones right now. We intend to make a more robust game as we have time, but for now this game does have several places where it may not be doing things in the most optimal way (such as using a non-typed AssetReference).

    After you've looked in the AssetReference code, please let me know if I'm misunderstanding your comment, or if our implementation somehow missed the mark.

    Thanks again for trying it out, and for your feedback. This is still in preview, so we really need all the feedback we can get to get it to a solid state.

    -Bill
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    You do support it for List, though. And Yaml definitely has space for it in the format. So it's doable.I have no idea how much work it is (probably a bunch), but I hope you at least consider adding another special case - like for List.
     
  5. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
  6. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    I've previously done something similar with Resources/Asset bundles where I instead added a PropertyAttribute that takes a type argument expose a direct reference field in the editor that explictly only accepts a certain type of asset from Resources/Asset bundles to be loaded. It wouldn't help if the type was ever changed, it would result in loading the wrong type of asset, as the serialized path wasn't changed, but it would stop my teammates from placing assets in the wrong location.

    Code (CSharp):
    1.  
    2. // Original version I wrote:
    3. [Resource(typeof(GameObject))]
    4. public string gameObjectAssetPath;
    5. public Resource<GameObject> gameObjectAsset = Resource.Get<GameObject>(gameObjectAssetPath);
    6. ...
    7. var gameObject = await gameObjectAsset.LoadAsync();
    8.  
    9. // Possible Addressables alternative:
    10. [AssetType(typeof(GameObject)]
    11. public AssetReference gameObjectAsset;
    12. gameObjectAsset.LoadAsset<GameObject>().Completed += (op) => {
    13.   gameObject = op.Result;
    14. };
    15.  
    16.  
    Though having the generic version of AssetReference would also have the added benefit of strong type safety when loading the asset.
     
    Last edited: Jul 3, 2018
  7. TomNCatz

    TomNCatz

    Joined:
    Jan 6, 2015
    Posts:
    24
    I know this is an old post, so maybe this wasn't true at the time, but you actually do have support for
    Code (CSharp):
    1. public GenericType<ConcreteType> myVariable;
    in Unity now. I have a scriptable object collection that uses it heavily and doesn't need anything special to be stored as a direct variable reference.

    For me not being able to make variables I'm exposing to designers type safe is a non-starter for this system. Our projects are too big and complex for me to expect them to remember all that kind of stuff. Hell I can't even remember what type goes in all of these fields without looking it up sometimes. And we have too many types we use for our solution to be a specialized wrapper for each type we want to expose.

    Hell, I can just write a generic object field that does it's own GUID lookup, checks the type, and stores the needed reference data and it will be more type safe than this...
     
    bluescrn likes this.