サイトアイコン StudioFun

Unity チュートリアルのタワーディフェンステンプレートを触ってみる(33)

Unity チュートリアルのタワーディフェンステンプレートを触ってみる(32)では引き続き「タワーディフェンステンプレートのステージの設定編」を行った。今回はレベルデータを保持している LevelList の解説を行っていく。

1.タワーディフェンステンプレートのステージの設定編 – LevelList.cs

LevelList.cs について稚拙ながら解説

「LevelList.cs」は「Assets/Scripts/Core/Game/LevelList.cs」の指しておりスクリプトについては以下の通り。内容としてはレベルデータのリストを保持している。

[cce_csharp]using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Core.Game
{
    /// <summary>
    /// Scriptable object for Level configuration
    /// </summary>
    [CreateAssetMenu(fileName = "LevelList", menuName = "StarterKit/Create Level List", order = 1)]
    public class LevelList : ScriptableObject, IList<LevelItem>,
                             IDictionary<string, LevelItem>, 
                             ISerializationCallbackReceiver
    {
        public LevelItem[] levels;

        /// <summary>
        /// Cached dictionary of levels by their IDs
        /// </summary>
        IDictionary<string, LevelItem> m_LevelDictionary;

        /// <summary>
        /// Gets the number of levels
        /// </summary>
        public int Count
        {
            get { return levels.Length; }
        }

        /// <summary>
        /// Level list is always read-only
        /// </summary>
        public bool IsReadOnly
        {
            get { return true; }
        }

        /// <summary>
        /// Gets a level by index
        /// </summary>
        public LevelItem this[int i]
        {
            get { return levels[i]; }
        }

        /// <summary>
        /// Gets a level by id
        /// </summary>
        public LevelItem this[string key]
        {
            get { return m_LevelDictionary[key]; }
        }

        /// <summary>
        /// Gets a collection of all level keys
        /// </summary>
        public ICollection<string> Keys
        {
            get { return m_LevelDictionary.Keys; }
        }

        /// <summary>
        /// Gets the index of a given level
        /// </summary>
        public int IndexOf(LevelItem item)
        {
            if (item == null)
            {
                return -1;
            }

            for (int i = 0; i < levels.Length; ++i)
            {
                if (levels[i] == item)
                {
                    return i;
                }
            }

            return -1;
        }

        /// <summary>
        /// Gets whether this level exists in the list
        /// </summary>
        public bool Contains(LevelItem item)
        {
            return IndexOf(item) >= 0;
        }

        /// <summary>
        /// Gets whether a level of the given id exists
        /// </summary>
        public bool ContainsKey(string key)
        {
            return m_LevelDictionary.ContainsKey(key);
        }

        /// <summary>
        /// Try get a level with the given key
        /// </summary>
        public bool TryGetValue(string key, out LevelItem value)
        {
            return m_LevelDictionary.TryGetValue(key, out value);
        }

        /// <summary>
        /// Gets the <see cref="LevelItem"/> associated with the given scene
        /// </summary>
        public LevelItem GetLevelByScene(string scene)
        {
            for (int i = 0; i < levels.Length; ++i)
            {
                LevelItem item = levels[i];
                if (item != null &&
                    item.sceneName == scene)
                {
                    return item;
                }
            }
            
            return null;
        }

        // Explicit interface implementations
        // Serialization listeners to create dictionary
        void ISerializationCallbackReceiver.OnBeforeSerialize()
        {
        }

        void ISerializationCallbackReceiver.OnAfterDeserialize()
        {
            m_LevelDictionary = levels.ToDictionary(l => l.id);
        }
        
        ICollection<LevelItem> IDictionary<string, LevelItem>.Values
        {
            get { return m_LevelDictionary.Values; }
        }

        LevelItem IList<LevelItem>.this[int i]
        {
            get { return levels[i]; }
            set { throw new NotSupportedException("Level List is read only"); }
        }

        LevelItem IDictionary<string, LevelItem>.this[string key]
        {
            get { return m_LevelDictionary[key]; }
            set { throw new NotSupportedException("Level List is read only"); }
        }

        void IList<LevelItem>.Insert(int index, LevelItem item)
        {
            throw new NotSupportedException("Level List is read only");
        }

        void IList<LevelItem>.RemoveAt(int index)
        {
            throw new NotSupportedException("Level List is read only");
        }

        void ICollection<LevelItem>.Add(LevelItem item)
        {
            throw new NotSupportedException("Level List is read only");
        }

        void ICollection<KeyValuePair<string, LevelItem>>.Add(KeyValuePair<string, LevelItem> item)
        {
            throw new NotSupportedException("Level List is read only");
        }

        void ICollection<KeyValuePair<string, LevelItem>>.Clear()
        {
            throw new NotSupportedException("Level List is read only");
        }

        bool ICollection<KeyValuePair<string, LevelItem>>.Contains(KeyValuePair<string, LevelItem> item)
        {
            return m_LevelDictionary.Contains(item);
        }

        void ICollection<KeyValuePair<string, LevelItem>>.CopyTo(KeyValuePair<string, LevelItem>[] array, int arrayIndex)
        {
            m_LevelDictionary.CopyTo(array, arrayIndex);
        }

        void ICollection<LevelItem>.Clear()
        {
            throw new NotSupportedException("Level List is read only");
        }

        void ICollection<LevelItem>.CopyTo(LevelItem[] array, int arrayIndex)
        {
            levels.CopyTo(array, arrayIndex);
        }

        bool ICollection<LevelItem>.Remove(LevelItem item)
        {
            throw new NotSupportedException("Level List is read only");
        }

        public IEnumerator<LevelItem> GetEnumerator()
        {
            return ((IList<LevelItem>) levels).GetEnumerator();
        }

        IEnumerator<KeyValuePair<string, LevelItem>> IEnumerable<KeyValuePair<string, LevelItem>>.GetEnumerator()
        {
            return m_LevelDictionary.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return levels.GetEnumerator();
        }

        void IDictionary<string, LevelItem>.Add(string key, LevelItem value)
        {
            throw new NotSupportedException("Level List is read only");
        }

        bool ICollection<KeyValuePair<string, LevelItem>>.Remove(KeyValuePair<string, LevelItem> item)
        {
            throw new NotSupportedException("Level List is read only");
        }

        bool IDictionary<string, LevelItem>.Remove(string key)
        {
            throw new NotSupportedException("Level List is read only");
        }
    }
}[/cce_csharp]

13行目 : 「public class LevelList : ScriptableObject, IList<LevelItem>, IDictionary<string, LevelItem>, ISerializationCallbackReceiver」は ScriptableObject を継承し、IList と IDictionary、ISerializationCallbackReceiver をインタフェースとしていることを指している。IList と IDictionary、ISerializationCallbackReceiver については DLL を呼び出すインタフェースのため、ここでは解説を省略させていただく。

112行目 : 「public LevelItem GetLevelByScene(string scene)」は LevelItem の配列から該当する Level の取得を行っている。

以降については既存の関数の呼び出しのみのため、解説はここまでとさせていただく。

モバイルバージョンを終了