内容
Unityにて、ゲーム中にプレイヤーたちの「名前」「キル数」を降順でランキング形式で表示したいです。
※イメージ↓
コード↓(こちらを参考にさせていただきました)
Scoreboard.cs
1using System.Collections; 2using System.Collections.Generic; 3using System; 4using UnityEngine; 5using UnityEngine.UI; 6using System.Linq; 7 8public class Scores{ 9 public string Name { get; set;} 10 public int Kill { get; set;} 11} 12 13public class Scoreboard : MonoBehaviour 14{ 15 public List<string> namesList = new List<string>(); //後でほかのオブジェクトからリストに追加されていく 16 public Text playernames_text; //名前テキスト 17 public Text playerkills_text; //キル数テキスト 18 public Text playerRank_text; //ランクテキスト 19 20 void Update(){ 21 var scores = new Scores[]{ 22 }; 23 foreach(string name in namesList){ 24 new Scores() 25 { 26 Name = name, 27 Kill = 0, 28 }; 29 } 30 //↑ダメ元でやってみたけどやっぱり無理だった。(そもそも表示されない) 31 var ranking = from s1 in scores 32 let higher = from s2 in scores // 現在の生徒より点数が良いプレイヤーを取得 33 where s2.Kill > s1.Kill 34 select s2 35 select new 36 { 37 s1.Name, 38 s1.Kill, 39 Rank = higher.Count() + 1, // 現在の生徒より点数が良い生徒の人数 + 1 が順位 40 } into s3 41 orderby s3.Rank // 順位で並び替え 42 select s3; 43 44 foreach(var scoreboard in ranking) 45 { 46 playerRank_text.text = scoreboard.Rank +"\n"; //改行 47 playernames_text.text = scoreboard.Name +"\n"; //改行 48 playerkills_text.text = scoreboard.Kill +"\n"; //改行 49 } 50 } 51}
Player.cs
1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class Player : MonoBehaviour 7{ 8 public string name; 9 public int kill = 0; //キル数 10 11 public Scoreboard scoreboard_script; 12 13 void Start () 14 { 15 //スコア 16 name = "a"; //とりあえず"a"とする 17 scoreboard_script.namesList.Add(name); //Scoreboard.csのnamesListに追加する 18 } 19}
今日「Linq」というものを知ったため、そもそもの書き方が間違っているかもしれません。
参考にしたサイトのように書くと以下↓のコードになりますが、これだと後でプレイヤーが増減したときに変更できないし...
※ちなみにUnityには表示されました(おかしいけど)
Scoreboard.cs
1 var scores = new Scores[]{ 2 new Scores(){ 3 Name = "a", 4 Kill = 0, 5 }, 6 new Scores() 7 { 8 Name = "b", 9 Kill = 1, 10 }, 11 };
どうすればうまく動作するのか、ご教授頂きたいです。
もし、ほかに実装できる方法があれば、それも合わせてご教授頂きたいです。
※抜けている箇所などがあれば修正または追記しますので、教えていただけるとありがたいです。
追記1
Player.csを追加しました。
追記2
"「長さが0の配列」になっている"との指摘を頂いたため、コードを書き換えたのですが、エラーが発生してしまいました。
Scoreboard.cs
1 var scores = new Scores[namesList.Count]; //配列の長さを名前リストと同じ長さにする 2 scores = namesList.ToArray(); //リストから配列に代入 3 //error CS0029: Cannot implicitly convert type 'string[]' to 'Scores[]' 4 foreach(var name in namesList){ 5 new Scores() 6 { 7 Name = name, 8 Kill = 0, 9 }; 10 }
エラー文
Console
1error CS0029: Cannot implicitly convert type 'string[]' to 'Scores[]'
"stringのリストは変換できません"みたいなことが書かれていますが、ではどうしたらいいのかさっぱりわかりません...
こちらのエラーについても、解決いただきたいです。
追記3
fiveHundredさんに教えてもらったようにFor文を使って追加するように書き換えましたが、For文の中でそれぞれのプレイヤーの名前は取得できているものの、うまくScores
に代入できていないようでして...
今一度解説をお願いしたいです。たくさんの追記申し訳ないです...
Scoreboard.cs
1 var scores = new Scores[namesList.Count]; 2 for (int i = 0; i < namesList.Count; i++){ 3 new Scores(){ 4 Name = namesList[i], 5 Kill = 0, 6 }; 7 };
実行したときのエラー文
Console
1NullReferenceException: Object reference not set to an instance of an object 2Scoreboard+<>c.<FixedUpdate>b__6_1 (<>f__AnonymousType0`2[<s1>j__TPar,<higher>j__TPar] <>h__TransparentIdentifier0) (at Scoreboard.cs:69) 3 4System.Linq.Utilities+<>c__DisplayClass2_0`3[TSource,TMiddle,TResult].<CombineSelectors>b__0 (TSource x) (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) 5System.Linq.Enumerable+SelectArrayIterator`2[TSource,TResult].ToArray () (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) 6System.Linq.Buffer`1[TElement]..ctor (System.Collections.Generic.IEnumerable`1[T] source) (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) 7System.Linq.OrderedEnumerable`1+<GetEnumerator>d__3[TElement].MoveNext () (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) 8Scoreboard.Update () (at Scoreboard.cs:78)
Scoreboard.cs
1//以下エラーの場所 2 var ranking = from s1 in scores 3 let higher = from s2 in scores // 現在のプレイヤーより点数が良いプレイヤーを取得 4 where s2.Kill > s1.Kill 5 select s2 6 select new //NullReferenceException:~ 7 { 8 s1.Name, 9 s1.Kill, 10 Rank = higher.Count() + 1, // 現在のプレイヤーより点数が良いプレイヤーの人数 + 1 が順位 11 } into s3 12 orderby s3.Rank // 順位で並び替え 13 select s3;
追記4(解決しました!!!)
fiveHundredさんに指摘された通り、代入がされていませんでしたが、追記のコード通りに書いたところ、見事に上手く動作しました!
↓早速作ったBotを入れて試してみました!
↓プレイヤーがBotをキルすると...
キル数が多い順にソートされた!!!(ちょっと不格好ですが...)
最後に
今回の不具合の原因は完全に私が名前を覚えたばっかりの「Linq」を全く学ばずにUnityに実装しようとしたことが原因です。
次回から新しいものに手を出す場合は、少しは基礎知識をつけたうえでコードを書いていこうと思います。
回答してくれた方々、どうもありがとうございました!
回答2件
あなたの回答
tips
プレビュー