追記
こちら、UnityのSpriteAtlasへの理解が完全に間違っていたため使用しないでください!
uGUIのImageをNGUIのUISpriteっぽく使えるように拡張しました.
ImageのパラメータにAtlasとSpriteNameを追加しました.
使い方
- SpriteAtlasを作る
- Pack PreviewでAtlasを作る
- Atlas ImageをアタッチしてAtlasを選択
- SpriteNameでAtlasに含まれる画像を設定する
スクリプト
AtlasImage.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.U2D;
public class AtlasImage : Image
{
[SerializeField] SpriteAtlas m_Atlas;
public SpriteAtlas atlas{ get{ return m_Atlas; } set{ m_Atlas = value;}}
[SerializeField] string m_SpriteName;
public string spriteName{
get{return m_SpriteName; }
set {
m_SpriteName = value;
if (atlas != null) {
this.sprite = atlas.GetSprite (m_SpriteName);
}
}
}
protected override void OnEnable(){
base.OnEnable ();
if (atlas != null)
this.sprite = atlas.GetSprite (spriteName);
}
}
AtlasImageEditor.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.UI;
using UnityEngine.U2D;
using System.Linq;
using UnityEditor.AnimatedValues;
using UnityEngine.UI;
[CustomEditor(typeof(AtlasImage), true)]
[CanEditMultipleObjects]
public class AtlasImageEditor : ImageEditor {
SerializedProperty m_Atlas;
SerializedProperty m_SpriteName;
AnimBool m_ShowSpriteName;
string[] atlasSpriteNames;
int spriteNameIndex = 0;
protected override void OnEnable ()
{
m_Atlas = serializedObject.FindProperty ("m_Atlas");
m_SpriteName = serializedObject.FindProperty ("m_SpriteName");
m_ShowSpriteName = new AnimBool (m_Atlas.objectReferenceValue != null);
m_ShowSpriteName.valueChanged.AddListener (Repaint);
ResetAtlasSpriteNames ();
ResetSpriteNameIndex ();
base.OnEnable ();
}
protected override void OnDisable ()
{
m_ShowSpriteName.valueChanged.RemoveListener (Repaint);
base.OnDisable ();
}
public override void OnInspectorGUI()
{
serializedObject.Update ();
AtlasGUI ();
m_ShowSpriteName.target = m_Atlas.objectReferenceValue != null;
if (EditorGUILayout.BeginFadeGroup (m_ShowSpriteName.faded))
SpriteNameGUI ();
EditorGUILayout.EndFadeGroup ();
serializedObject.ApplyModifiedProperties ();
base.OnInspectorGUI ();
}
protected virtual void AtlasGUI(){
EditorGUI.BeginChangeCheck ();
EditorGUILayout.PropertyField (m_Atlas);
if (EditorGUI.EndChangeCheck ()) {
ResetAtlasSpriteNames ();
ResetSpriteNameIndex ();
}
}
// 現在の名前からindexを求める
void ResetSpriteNameIndex(){
if (atlasSpriteNames == null || atlasSpriteNames.Length == 0)
return;
string currentName = m_SpriteName.stringValue;
int tempIndex = 0;
for (int i = 0; i < atlasSpriteNames.Length; i++) {
if (currentName == atlasSpriteNames [i]) {
tempIndex = i;
break;
}
}
spriteNameIndex = tempIndex;
m_SpriteName.stringValue = atlasSpriteNames [spriteNameIndex];
UpdateSourceImage ();
}
void ResetAtlasSpriteNames(){
var newAtlas = m_Atlas.objectReferenceValue as SpriteAtlas;
if (newAtlas) {
atlasSpriteNames = GetAllSprite (newAtlas)
.Select (x => x.name.Replace ("(Clone)", ""))
.ToArray ();
}
}
protected virtual void SpriteNameGUI(){
EditorGUI.BeginChangeCheck ();
if (atlasSpriteNames != null)
spriteNameIndex = EditorGUILayout.Popup ("SpriteName", spriteNameIndex, atlasSpriteNames);
if (EditorGUI.EndChangeCheck ()) {
m_SpriteName.stringValue = atlasSpriteNames [spriteNameIndex];
UpdateSourceImage ();
}
}
protected virtual void UpdateSourceImage(){
SerializedProperty m_Type = serializedObject.FindProperty("m_Type");
SerializedProperty m_Sprite = serializedObject.FindProperty("m_Sprite");
var currentAtlas = m_Atlas.objectReferenceValue as SpriteAtlas;
if (currentAtlas == null)
return;
var newSprite = currentAtlas.GetSprite (m_SpriteName.stringValue);
m_Sprite.objectReferenceValue = newSprite;
if (newSprite)
{
Image.Type oldType = (Image.Type)m_Type.enumValueIndex;
if (newSprite.border.SqrMagnitude() > 0)
{
m_Type.enumValueIndex = (int)Image.Type.Sliced;
}
else if (oldType == Image.Type.Sliced)
{
m_Type.enumValueIndex = (int)Image.Type.Simple;
}
}
}
static IEnumerable<Sprite> GetAllSprite(SpriteAtlas spriteAtlas){
//spriteの空の配列を作成、サイズはAtlasに含まれるSpriteの数
Sprite[] spriteArray = new Sprite[spriteAtlas.spriteCount];
//spriteArrayに全Spriteを設定
spriteAtlas.GetSprites(spriteArray);
foreach (var sprite in spriteArray) {
yield return sprite;
}
}
}
AtlasImageEditor.csはEditor
という名前のフォルダを作ってその中に作成してください.
# まとめ
AtlasImage.csの方は最小限のコードしかしれていないので,今後拡張していくつもりです.
AssetBundleの仕様変更がきたときに改修かけると思います.
もっと良い方法あれば教えていただけると嬉しいです!