あらまし
- Resourcesのリソースをインスタンス変数として持ちたい(AudioClipとか、Prefabとか)
- でもResources.Loadはランタイムにしか呼べない
- その変数が使われる時はランタイムであることが保証されている(StartとかUpdateとか)
- なんかLazyないっぽい?
=> よし、Lazy作ろう
結論
こんな感じのLazyクラスを作ればよい
using System;
using UnityEngine;
namespace Hexat
{
// Basic
public class Lazy<TParam, TOut>
{
protected TParam param;
protected TOut value;
protected Func<TParam, TOut> provider;
public Lazy(TParam param, Func<TParam, TOut> provider)
{
this.param = param;
this.provider = provider;
}
public TOut Value
{
get { return value != null ? value : (value = provider(param)); }
}
}
// Without initialization params
public sealed class LazyObject<T> : Lazy<object, T>
{
public LazyObject(Func<T> provider) : base(null, o => provider())
{
}
}
// Resource
public sealed class LazyResource<T> : Lazy<string, T> where T : UnityEngine.Object
{
public LazyResource(string path) : base(path, Resources.Load<T>)
{
}
}
}
使い方
音を鳴らす感じのクラス
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Hexat
{
public sealed class SoundManager : MonoBehaviour
{
private static LazyResource<AudioClip> LazyAudio(string name)
{
return new LazyResource<AudioClip>(name);
}
private Dictionary<string, LazyResource<AudioClip>> _clips = new Dictionary<string, LazyResource<AudioClip>>()
{
{Sounds.SE_PLAYER_CRASH, LazyAudio("Sounds/crash")},
{Sounds.SE_PLAYER_JUMP, LazyAudio("Sounds/jump")},
{Sounds.SE_PLAYER_EQUIP, LazyAudio("Sounds/equip")}
};
private Dictionary<int, AudioSource> _channels = new Dictionary<int, AudioSource>();
private AudioSource GetChannel(int channel)
{
if (_channels.ContainsKey(channel)) return _channels[channel];
return _channels[channel] = gameObject.AddComponent<AudioSource>();
}
private AudioClip GetClip(string clip)
{
return _clips[clip].Value;
}
public void Play(string key, int channel = 0)
{
var cnl = GetChannel(channel);
var clp = GetClip(key);
cnl.clip = clp;
cnl.Play();
}
}
}