Default values for meshes, textures, etc.

This is a thing I kind of miss from some other development environments, is there any way to do this in Unity?

class Foo {
 private Material myMaterial = ["Assets/Materials/FooMaterial"];
 private Texture2D myTexture = ["Assets/Textures/FooTexture.png"];
}

Assume for the sake of argument that I’m not going to instantiate the Foo class from a prefab, I’m going to attach it through AddComponent. So it’s not viable to assign them through the Editor. And it kind of goes against encapsulating the Foo class if anything that attaches a Foo component has to manage and pass all these variable to the Foo component and can never let the Foo component handle it.

I suppose I can assign a value in the Start function using Resources.Load() is that the only way to identify assets through script?

Resources.Load does exactly this, is there a reason you don’t want to use it?

1 Like

To keep it all in one place, I like the Factory Pattern. In Unity it can take a number of shapes, but here’s one:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyScript : MonoBehaviour
{
    public    static    MyScript    Load(
        string resourcesPath, string additionalArgument1, int otherArgument)
    {

       // code for if this is a pre-defined prefab that you're going
       // to load, instantiate, and then customize a bit
        GameObject go = Resources.Load<GameObject>( resourcesPath);
        go = Instantiate<GameObject>( go);
        MyScript myScript = go.GetComponent<MyScript>();

       // OR: code for making a new GameObject from scratch
        MyScript myScript = new GameObject( "MyScript.Create();").
            AddComponent<MyScript>();

       // only have ONE of the two blocks of code above!!

        // jam in the arguments we need
        myScript.additionalArgument1 = additionalArgument1;
        myScript.otherArgument = otherArgument;

        return myScript;
    }

    string additionalArgument1;
    int otherArgument;

    void Start()
    {
        /// etc...
    }

    void Update()
    {
        /// etc...
    }
}

Remember, anything you load with Resources.Load() has to be under a folder somewhere named Resources.

Maybe the real problem is that Resources.Load doesn’t let you load Meshes, it only lets you load a GameObject that has Meshes attached to it and then you have to extract Meshes out of it, which seems like an inelegant way to handle this when I just want the Mesh. Whereas you can assign Meshes directly to serialized fields in the editor, but to take advantage of that you have to create this GameObject from a prefab rather than adding it as a component to an existing object.

Resources.Load would bother me less for Textures and Materials because you’re allowed to load them directly, I suppose.

Well, that’s a thing for sure… but never fear! Unity is AMAZINGLY flexible, and you can achieve essentially the same thing this way: you make a MeshCollection ScriptableObject instance that contains all your meshes (you have to drag the references in there), and then you can use that MeshCollection instance to retrieve meshes by name.

Here’s a quickie script I threw together, modeled after my GameObjectCollection class:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu]
public class MeshCollection : ScriptableObject
{
    public Mesh[] Meshes;

    public int    Count
    {
        get
        {
            if (Meshes != null) return Meshes.Length;
            return 0;
        }
    }

    public Mesh Find( string searchFor, bool ignoreCase = true)
    {
        if (ignoreCase)
        {
            searchFor = searchFor.ToLower();
        }
           
        foreach( var m in Meshes)
        {
            var n = m.name;

            if (ignoreCase)
            {
                n = n.ToLower();
            }

            if (n == searchFor)
            {
                return m;
            }
        }
        return null;
    }
}

You can make as many collections as you want, like for theming or skinning. You can even make a “give me a random mesh” function inside there.

You would drag all the meshes into the instance of MeshCollection in the editor, like so:

5303199--532785--Screen Shot 2019-12-20 at 11.44.32 AM.png

Then you can get at them by name using Find().