new演算子を使ったインスタンスの作成(Unity編共通インスタンス)
インスタンスの作成を作成するクラス自身で行うパターンを使ったランキング情報の管理の方法を学びます
基本パターン
シーンの構成
次を参考にしましょう

Rankerクラス
基本
インスタンスを作る元のクラスです
ランキングを叩き出した人の名前とポイント情報がメンバーとして記録しています
public class Ranker
{
public string name;
public int score;
}
初期値設定機能
初期値を設定するために引数付きコンストラクタを追加します
public class Ranker
{
public string name;
public int score;
public Ranker(string name, int score)
{
this.name = name;
this.score = score;
}
}
Rankingクラス
基本
ランキング情報をリストにしたものをメンバーとして持っています
using System.Collections.Generic;
public class Ranking
{
List<Ranker> rankers = new List<Ranker>();
}
スコア情報追加機能
Addメソッドを追加します
呼ばれるとスコアのリストに新しく追加されます
using System.Collections.Generic;
public class Ranking
{
List<Ranker> rankers = new List<Ranker>();
public void Add(string name, int score)
{
Ranker ranker = new Ranker(name, score);
rankers.Add(ranker);
}
}
インスタンスを取得するクラス
using UnityEngine;
public class Sample : MonoBehaviour
{
void Start()
{
Ranking ranking = new Ranking();
ranking.Add("太郎", 70);
ranking.Add("次郎", 60);
}
}
スコア情報削除機能
Removeメソッドを追加します
呼ばれるとスコアのリストから該当するスコア情報を削除します
using System.Collections.Generic;
public class Ranking
{
List<Ranker> rankers = new List<Ranker>();
public void Add(string name, int score)
{
Ranker ranker = new Ranker(name, score);
rankers.Add(ranker);
}
public void Remove(string name)
{
rankers.Remove(rankers.Find(ranker => ranker.name == name));
}
}
rankers.Remove(rankers.Find(ranker => ranker.name == name));
ラムダ記号を分解していきます(インテリセンスがやってくれます)
rankers.Remove(rankers.Find(ranker =>
{
return ranker.name == name;
}));
わざわざ、メソッドにして名前をつけます(実はRemoveメソッドの引数はメソッドの型ということ)
スコアリストの中から調べたい名前で探して見つかれば戻すということをやっているのがわかります
public void Remove(string name)
{
rankers.Remove(FindRanker(name));
}
Ranker FindRanker(string name)
{
foreach (var ranker in rankers)
{
if (ranker.name == name)
{
return ranker;
}
}
return null;
}
インスタンスを取得するクラス
using UnityEngine;
public class Sample : MonoBehaviour
{
void Start()
{
Ranking ranking = new Ranking();
ranking.Add("太郎", 70);
ranking.Add("次郎", 60);
ranking.Add("三郎", 50);
ranking.Remove("次郎");
}
}
スコアリスト取得機能
プロパティを窓口として、取得するようにします
getアクセサのみにすることで書き込みはできないようにします
public修飾子も確認してください
using System.Collections.Generic;
public class Ranking
{
List<Ranker> rankers = new List<Ranker>();
public List<Ranker> Rankers => rankers;
public void Add(string name, int score)
{
Ranker ranker = new Ranker(name, score);
rankers.Add(ranker);
}
public void Remove(string name)
{
rankers.Remove(rankers.Find(ranker => ranker.name == name));
}
}
public List<Ranker> Rankers => rankers;
ラムダ記号を分解します(インテリセンスがやってくれます)
public List<Ranker> Rankers
{
get
{
return rankers;
}
}
インスタンスを取得するクラス
using System.Collections.Generic;
using UnityEngine;
public class Sample : MonoBehaviour
{
void Start()
{
Ranking ranking = new Ranking();
ranking.Add("太郎", 70);
ranking.Add("次郎", 60);
ranking.Add("三郎", 50);
ranking.Remove("次郎");
List<Ranker> rankers = ranking.Rankers;
foreach (var ranker in rankers)
{
Debug.Log($"名前:{ranker.name} ポイント:{ranker.score}");
}
}
}
結果
名前:太郎 ポイント:70
名前:三郎 ポイント:50
スコアリスト取得機能(スコアの高い順で並び替えて取得)
これまでのサンプルでは、追加順に取得していますが、実際ではスコアが高い順に欲しいですよね
using System.Collections.Generic;
using System.Linq;
public class Ranking
{
List<Ranker> rankers = new List<Ranker>();
public List<Ranker> Rankers => rankers.OrderByDescending(ranker => ranker.score).ToList();
public void Add(string name, int score)
{
Ranker ranker = new Ranker(name, score);
rankers.Add(ranker);
}
public void Remove(string name)
{
rankers.Remove(rankers.Find(ranker => ranker.name == name));
}
}
rankers.OrderByDescending(ranker => ranker.score).ToList();
ラムダ記号を分解します(インテリセンスがやってくれます)
public List<Ranker> Rankers => rankers.OrderByDescending(ranker =>
{
return ranker.score;
}).ToList();
OrderByDescendingメソッドな、LINQのメソッドです
降順(大きい順)に並び替えられます
引数に並び替えの基準を記述します
今回は、スコア順としたいのでscoreを渡します
インスタンスを取得するクラス
using System.Collections.Generic;
using UnityEngine;
public class Sample : MonoBehaviour
{
void Start()
{
Ranking ranking = new Ranking();
ranking.Add("太郎", 70);
ranking.Add("次郎", 60);
ranking.Add("三郎", 50);
ranking.Remove("次郎");
ranking.Add("四郎", 65);
List<Ranker> rankers = ranking.Rankers;
foreach (var ranker in rankers)
{
Debug.Log($"名前:{ranker.name} ポイント:{ranker.score}");
}
}
}
結果
点数の高い順に並び替えられたのを取得できています
名前:太郎 ポイント:70
名前:四郎 ポイント:65
名前:三郎 ポイント:50
Rankingクラス内にRankerクラスを取り込む
シーンの構成

Rankingクラス
基本
Rankerクラスをコピーして貼り付けています
using System.Collections.Generic;
using System.Linq;
public class Ranking
{
public class Ranker
{
public string name;
public int score;
public Ranker(string name, int score)
{
this.name = name;
this.score = score;
}
}
List<Ranker> rankers = new List<Ranker>();
public List<Ranker> Rankers => rankers.OrderByDescending(ranker =>
{
return ranker.score;
}).ToList();
public void Add(string name, int score)
{
Ranker ranker = new Ranker(name, score);
rankers.Add(ranker);
}
public void Remove(string name)
{
rankers.Remove(rankers.Find(ranker => ranker.name == name));
}
}
インスタンスを取得するクラス
using System.Collections.Generic;
using UnityEngine;
public class Sample : MonoBehaviour
{
void Start()
{
Ranking ranking = new Ranking();
ranking.Add("太郎", 70);
ranking.Add("次郎", 60);
ranking.Add("三郎", 50);
ranking.Remove("次郎");
ranking.Add("四郎", 65);
List<Ranking.Ranker> rankers = ranking.Rankers;
foreach (var ranker in rankers)
{
Debug.Log($"名前:{ranker.name} ポイント:{ranker.score}");
}
}
}
Rankingクラスが単純にインスタンス化できるとまずい?
例えば、UIの表示の時など様々なところでRinkingが必要になることがあります
その都度、new Ranking()としてしまうと新しいインスタンスが作られ情報を共有することができません
そこで、何回呼ばれても同じインスタンスを戻すようにします
これをシングルトンパターンといいます
シーンの構成

Rankingクラスに追加するシングルトンパターンのコード
外部から、new Ranking()でインスタンスを作成するのではなく、GetInstanceメソッドを呼び出してもらいます
戻り値がこのクラスのインスタンスになります
2回目からは1回目で作成されたインスタンスが返されます
追加するコード
// プライベートコンストラクタ
// public 修飾子でないので、他のクラスからnewできません(エラーになります)
Ranking()
{
}
static Ranking instance;
// staticなので、他のクラスからは、クラス名.プロパティ名でアクセスします
// Ranking.GetInstanceで読み取ります
public static Ranking GetInstance
{
get
{
if (instance == null)
{
instance = new Ranking();
}
return instance;
}
}
シングルトンを使ったRankingクラス
using System.Collections.Generic;
using System.Linq;
public class Ranking
{
Ranking()
{
}
static Ranking instance;
public static Ranking GetInstance
{
get
{
if (instance == null)
{
instance = new Ranking();
}
return instance;
}
}
public class Ranker
{
public string name;
public int score;
public Ranker(string name, int score)
{
this.name = name;
this.score = score;
}
}
List<Ranker> rankers = new List<Ranker>();
public List<Ranker> Rankers => rankers.OrderByDescending(ranker =>
{
return ranker.score;
}).ToList();
public void Add(string name, int score)
{
Ranker ranker = new Ranker(name, score);
rankers.Add(ranker);
}
public void Remove(string name)
{
rankers.Remove(rankers.Find(ranker => ranker.name == name));
}
}
インスタンスを取得するクラス
new Ranking();のところをRanking.GetInstance;に変えています
using UnityEngine;
public class Sample : MonoBehaviour
{
void Start()
{
Ranking ranking = Ranking.GetInstance;
ranking.Add("太郎", 70);
ranking.Add("次郎", 60);
ranking.Add("三郎", 50);
ranking.Remove("次郎");
ranking.Add("四郎", 65);
foreach (var ranker in ranking.Rankers)
{
Debug.Log($"名前:{ranker.name} ポイント:{ranker.score}");
}
}
}
インスタンスを取得するクラス(UIを表示するクラスシミュレーション)
using UnityEngine;
public class UISample : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Ranking ranking = Ranking.GetInstance;
ranking.Add("五郎", 75);
ranking.Add("六郎", 88);
ranking.Add("七郎", 20);
ranking.Remove("七郎");
ranking.Add("八郎", 10);
foreach (var ranker in ranking.Rankers)
{
Debug.Log($"名前:{ranker.name} ポイント:{ranker.score}");
}
}
}
}
結果
点数の高い順に並び替えられたのを取得できています
スペースキーを押す前
名前:太郎 ポイント:70
名前:四郎 ポイント:65
名前:三郎 ポイント:50
スペースキーを押した後(コンソールウィンドウでClearボタンをクリックすると上記は消えるので見やすいです)
名前:六郎 ポイント:88
名前:五郎 ポイント:75
名前:太郎 ポイント:70
名前:四郎 ポイント:65
名前:三郎 ポイント:50
名前:八郎 ポイント:10
テスト結果を確認するためのブレークポイント
Macでのブレークポイント設定ですが、基本Windowsでも同じです

ディスカッション
コメント一覧
まだ、コメントがありません