- 投稿日:2019-04-30T23:54:27+09:00
[C#]実装で見返すリンク集
LINQ
LINQでの記載に迷った時
C# LINQ サンプル集
LINQチートシート的なものWhereを使ったがもっと良い記載がないか疑問に思った時
LINQ、そのWhere本当に必要ですか?コレクション
コレクションの継承関係や一覧が見たい時
意外と知らない!? C#の便利なコレクション!どのコレクションを使うか迷った時
C#(.NET)コレクションの使い分けヒント簡略化された継承関係図を見たい時、メソッド引数や戻り値としてどのコレクションを使うか迷った時
引数の型を何でも List にしちゃう奴にそろそろ一言いっておくかMoq
Mockの記載に迷った時
【C#】【Mock】Moq ~ 文法編 ~delegate
再復習したい時
なんとなくで来ちゃった人向けのデリゲートとイベントハンドラ再復習ラムダ式
再復習したい時
C# 今更ですが、ラムダ式MicrosoftのReferenceSource
メソッドの中身が見たい時
https://referencesource.microsoft.com/その他
NULL三兄弟(Null許容型/Null条件演算子/Null合体演算子)について
https://www.wareko.jp/blog/nullable-type-null-condition-operator-null-coalescing-operator-three-nulls-brothersStringとstringの違い
大文字のStringを使う場合は、「System名前空間」のusingが必要。
小文字のstringを使う場合は、usingは不要。
https://kuroeveryday.blogspot.com/2014/09/string.htmlyield について
https://csharp.keicode.com/basic/yield.php
- 投稿日:2019-04-30T18:22:51+09:00
Unityで使うランキング表示用サーバーを作る話
どうも洋梨?です。
ゲームによくある「スコアランキング」ですが、この機能を実装していくまでの話を簡単に書いていきます。
こちらも是非ご覧ください。環境
テスト環境としてXAMPP
データーベースはMySQL (MariaDB)
サーバーはNode.js
フロント側はUnityで行っています。
データーベースを構築する
今回構築するデーターベースは
id(プレイヤー のID) ,name (プレイヤー の名前) ,score (プレイヤーの点数) ,date(記録した日時)
を保存するものとします。
今回はテストとしてデーターをいくつか追加しておきます。なお、テーブル名は”RANK“としてます。
Node.jsでサーバーを構築
今回フレームワークとして Express を使用します。
なお、サーバーはポート番号:3000で待ち受け、 localhost:3000/Getにアクセスされ、データーの一覧をjson形式で返すものとします。
main.jsconst exp = require("express"); const app = exp(); app.listen(3000,function(){ console.log("Start Server."); }) const mysql = require('mysql'); app.get("/Get",function(req,res,nex){ let con = mysql.createConnection({ host : 'localhost', user : 'root', port : 3306, database : 'test' }); con.query("SELECT * FROM RANK",function(e,r){ console.log(r); response(res,"OK",r); }) }) function response(res,result,data){ let resJson = {status:result,data:data} res.json(resJson); }
実行した後、ブラウザなどでアクセスすると動いているのを確認できると思います。Unityでサーバから情報を受け取る
まずはUnity上でサーバーから受信できるかをテストします。
画面のGETボタンをクリックしたら受信をするようにします。
Test.cspublic void OnPushGET() { var req = WebRequest.Create("http://localhost:3000/Get"); var res = req.GetResponse(); using (Stream stm = res.GetResponseStream()) using(StreamReader str = new StreamReader(stm)) { string json = str.ReadToEnd(); Debug.Log(json); } }取得できている場合、ログに出力されると思います。
デシリアライズし、使える形式にする
JsonData.cs[Serializable] public class Json { public string status; public Data[] data; } [Serializable] public class Data { public string id; public string name; public int score; public string date; }シリアライズに使うクラス(構造)はこんな感じです。
サーバーからのリスポンス(JSON)はこのようなデーターですTest.cspublic void OnPushGET() { var req = WebRequest.Create("http://localhost:3000/Get"); var res = req.GetResponse(); using (Stream stm = res.GetResponseStream()) using(StreamReader str = new StreamReader(stm)) { string json = str.ReadToEnd(); Debug.Log(json); Json j = JsonUtility.FromJson<Json>(json); string s = "結果\n"; foreach (Data data in j.data) s += "[" + data.name + "] Score:" + data.score + "\n"; text.text = s; } }先ほど書いたソースコードを受信したJSONデーターを表示するように書き換えます。
成功するとこのように表示されます。
これでUnity上でサーバーから取得した情報が使えるようになりました。
データーベースに情報を登録する
次はUnityからサーバーにスコア(情報)を登録できるようにしていきたいと思います。
リクエスト構造(JSON)
今回サーバーに送信するリクエスト形式は次のようにしました。
JSON { id , action, name , score }
id : ユーザー識別用ID
action : 操作内容(例:追加 = ADD)
name : ユーザー名
score : スコアリクエストを処理する(サーバー側)
まずはNode.jsでリクエストを処理するためのプログラムを作成します。
今回は追加(ADD)リクエストが来たらとりあえず何も考えずデーターベースに登録するとします。
なお、リクエスト先は localhost:3000/post とします。main.jsapp.post("/Post",function(req,res,nex){ let b = req.body; console.log("POST Receive. ["+b+"]"); database_action(res,b.id,b.action,b.name,b.score); }) function database_action(res,id,action,name,score){ switch(action){ case "ADD": console.log("Run Query : INSERT INTO RANK VALUES("+id+","+name+","+score+",now())"); con.query("INSERT INTO RANK VALUES('"+id+"','"+name+"',"+score+",now())",function(e,r){ if(e) response(res,"ERROR",null); else response(res,"OK",null); }) break; } }リクエストを送信する(Unity)
テストデーターとして
{ id:”a003” , action:”ADD” , name:”MyUser” , score:300 }
を送信するとします。
なお、送信はPOSTで行います。Test.cspublic void OnPushPost() { var send = "{ \"id\":\"a003\" , \"action\" : \"ADD\" ,\"name\":\"MyUser\" ,\"score\": 300 }"; var bytes = System.Text.Encoding.UTF8.GetBytes(send); var req = WebRequest.Create("http://localhost:3000/Post"); req.Method = "POST"; req.ContentType = "application/json; charset=utf-8"; req.ContentLength = bytes.Length; req.Timeout = 3000; var reqStm = req.GetRequestStream(); reqStm.Write(bytes, 0, bytes.Length); var res = req.GetResponse(); using (Stream stm = res.GetResponseStream()) using (StreamReader str = new StreamReader(stm)) { string json = str.ReadToEnd(); Debug.Log(json); } Debug.Log("Send POST:" + bytes.Length); reqStm.Close(); res.Close(); }実行してみるとデーターベースに登録されているのがわかると思います。
↑ リクエスト送信前と送信後でデーターが追加されているのがわかる
送信後 /Get でリストを取得すると確かに登録されていることが確認できます。これでUnityからサーバーに登録もできるようになり、ランキング表示機能として使えるようになりました?
- 投稿日:2019-04-30T18:22:51+09:00
Unityで使うランキング表示用サーバーを作った話
どうも洋梨?です。
ゲームによくある「スコアランキング」ですが、この機能を実装していくまでの話を簡単に書いていきます。
こちらも是非ご覧ください。環境
テスト環境としてXAMPP
データーベースはMySQL (MariaDB)
サーバーはNode.js
フロント側はUnityで行っています。
データーベースを構築する
今回構築するデーターベースは
id(プレイヤー のID) ,name (プレイヤー の名前) ,score (プレイヤーの点数) ,date(記録した日時)
を保存するものとします。
今回はテストとしてデーターをいくつか追加しておきます。なお、テーブル名は”RANK“としてます。
Node.jsでサーバーを構築
今回フレームワークとして Express を使用します。
なお、サーバーはポート番号:3000で待ち受け、 localhost:3000/Getにアクセスされ、データーの一覧をjson形式で返すものとします。
main.jsconst exp = require("express"); const app = exp(); app.listen(3000,function(){ console.log("Start Server."); }) const mysql = require('mysql'); app.get("/Get",function(req,res,nex){ let con = mysql.createConnection({ host : 'localhost', user : 'root', port : 3306, database : 'test' }); con.query("SELECT * FROM RANK",function(e,r){ console.log(r); response(res,"OK",r); }) }) function response(res,result,data){ let resJson = {status:result,data:data} res.json(resJson); }
実行した後、ブラウザなどでアクセスすると動いているのを確認できると思います。Unityでサーバから情報を受け取る
まずはUnity上でサーバーから受信できるかをテストします。
画面のGETボタンをクリックしたら受信をするようにします。
Test.cspublic void OnPushGET() { var req = WebRequest.Create("http://localhost:3000/Get"); var res = req.GetResponse(); using (Stream stm = res.GetResponseStream()) using(StreamReader str = new StreamReader(stm)) { string json = str.ReadToEnd(); Debug.Log(json); } }取得できている場合、ログに出力されると思います。
デシリアライズし、使える形式にする
JsonData.cs[Serializable] public class Json { public string status; public Data[] data; } [Serializable] public class Data { public string id; public string name; public int score; public string date; }シリアライズに使うクラス(構造)はこんな感じです。
サーバーからのリスポンス(JSON)はこのようなデーターですTest.cspublic void OnPushGET() { var req = WebRequest.Create("http://localhost:3000/Get"); var res = req.GetResponse(); using (Stream stm = res.GetResponseStream()) using(StreamReader str = new StreamReader(stm)) { string json = str.ReadToEnd(); Debug.Log(json); Json j = JsonUtility.FromJson<Json>(json); string s = "結果\n"; foreach (Data data in j.data) s += "[" + data.name + "] Score:" + data.score + "\n"; text.text = s; } }先ほど書いたソースコードを受信したJSONデーターを表示するように書き換えます。
成功するとこのように表示されます。
これでUnity上でサーバーから取得した情報が使えるようになりました。
データーベースに情報を登録する
次はUnityからサーバーにスコア(情報)を登録できるようにしていきたいと思います。
リクエスト構造(JSON)
今回サーバーに送信するリクエスト形式は次のようにしました。
JSON { id , action, name , score }
id : ユーザー識別用ID
action : 操作内容(例:追加 = ADD)
name : ユーザー名
score : スコアリクエストを処理する(サーバー側)
まずはNode.jsでリクエストを処理するためのプログラムを作成します。
今回は追加(ADD)リクエストが来たらとりあえず何も考えずデーターベースに登録するとします。
なお、リクエスト先は localhost:3000/post とします。main.jsapp.post("/Post",function(req,res,nex){ let b = req.body; console.log("POST Receive. ["+b+"]"); database_action(res,b.id,b.action,b.name,b.score); }) function database_action(res,id,action,name,score){ switch(action){ case "ADD": console.log("Run Query : INSERT INTO RANK VALUES("+id+","+name+","+score+",now())"); con.query("INSERT INTO RANK VALUES('"+id+"','"+name+"',"+score+",now())",function(e,r){ if(e) response(res,"ERROR",null); else response(res,"OK",null); }) break; } }リクエストを送信する(Unity)
テストデーターとして
{ id:”a003” , action:”ADD” , name:”MyUser” , score:300 }
を送信するとします。
なお、送信はPOSTで行います。Test.cspublic void OnPushPost() { var send = "{ \"id\":\"a003\" , \"action\" : \"ADD\" ,\"name\":\"MyUser\" ,\"score\": 300 }"; var bytes = System.Text.Encoding.UTF8.GetBytes(send); var req = WebRequest.Create("http://localhost:3000/Post"); req.Method = "POST"; req.ContentType = "application/json; charset=utf-8"; req.ContentLength = bytes.Length; req.Timeout = 3000; var reqStm = req.GetRequestStream(); reqStm.Write(bytes, 0, bytes.Length); var res = req.GetResponse(); using (Stream stm = res.GetResponseStream()) using (StreamReader str = new StreamReader(stm)) { string json = str.ReadToEnd(); Debug.Log(json); } Debug.Log("Send POST:" + bytes.Length); reqStm.Close(); res.Close(); }実行してみるとデーターベースに登録されているのがわかると思います。
↑ リクエスト送信前と送信後でデーターが追加されているのがわかる
送信後 /Get でリストを取得すると確かに登録されていることが確認できます。これでUnityからサーバーに登録もできるようになり、ランキング表示機能として使えるようになりました?
- 投稿日:2019-04-30T15:11:04+09:00
【Unity(C#)】Particleの粒子を一つだけ出してそのポジションを取得する方法
Particle
Particleに関する知識が浅かったので少し沼にはまりました。
同じ苦しみを味わう人がいなくなることを願って書きます。
Particleはパラメーターが多いので
Unityを触り初めたばかりの頃は見てるだけで吐き気がしました。とはいえ、上手く使えばとても便利なのは明白なのでマスターしといて損はないです。
経緯
Unityで花火を作っていたのですが、音が耳元で鳴ることに違和を感じました。
そこで、
①花火が打ちあがった先のポジションを取得
②AudioSource付きオブジェクトを取得した位置に移動
③AudioSourceから音源を再生という流れならいけるのでは?と思い試しました。
花火
Particleを使った花火の作り方はこちらをご覧ください→花火
非常にわかりやすくまとめられているので小一時間でいい感じのものが完成します。
Particleの粒子
今回の作り方は簡潔にまとめると
①花火の種が1つ打ちあがる(Particleの粒子1つ)
②花火の種が消える
③花火のParticleが広がる
という構成です。ここで一つ沼にはまる要因がありまして、
花火の種がParticle粒子であるため、普通のゲームオブジェクトのように
ゲームオブジェクト名.transform.positionでポジションを取得できないという点です。なので、普段のポジションの取得の仕方に比べ、遠回りして取得しなければなりません。
Particle粒子のポジション取得方法
AudioSource付きゲームオブジェクトにアタッチ//花火の種のParticleSystem [SerializeField] ParticleSystem _particleSystem; ParticleSystem.Particle[] particles; int particleNum; void Start() { particles = new ParticleSystem.Particle[_particleSystem.emission.burstCount]; } void Update() { //パーティクルの粒子が存在しているか確認 if (_particleSystem.particleCount > 0) { particleNum = _particleSystem.GetParticles(particles); Vector3 particleSeedPosition = particles[0].position; this.gameObject.transform.position = particleSeedPosition; } else if (particleNum > 0 && _particleSystem.particleCount == 0) { //音源再生の処理 particleNum--; AudioSource audioSource = this.gameObject.GetComponent<AudioSource>(); audioSource.Play(); } }まず
ParticleSystem.Particleの中に取得したい粒子を全部入れてしまいます。
今回は一つしか出ない設定なので1と直接書いてしまっても問題ないかと思います。
パラメーターから粒子の数を取得したい場合は
上の画像のCountの下の数字を取得してくればいいので
配列初期化時の要素数に_particleSystem.emission.burstCountを与えてあげれば可能です。あとは
_particleSystem.GetParticles(particles)とすることで
指定したParticleSystem内の粒子を全て取得することができます。Vector3 particleSeedPosition = particles[0].position;最後に
particlesのindexに先頭である0を指定して
粒子のポジション取得が完了です。GetParticles
スクリプトリファレンスにも記述ありましたが、
GetParticlesは現時点で生存しているParticleの粒子を取得するので、
Start内で呼び出してしまうとまだ存在していない粒子に対してGet(取得)してしまうことになり、
うまくいきませんでした。デモ
AudioSourceが一緒に移動しているのがわかるかと思います。
前例が少ない、
エラーが出ない、
などなど、深い沼だった...この沼から出れた瞬間の快感、病みつきになりますね。
- 投稿日:2019-04-30T14:07:20+09:00
【Unity】テストを全く知らない初心者が勉強に利用したリンク集
上から順に見ていくと良いと思います。
情報が古いものもありますが、適宜公式マニュアルを参照しながら読み替えてください。【Unite 2017 Tokyo】バグを殲滅!Unityにおける実践テスト手法
Unity使いは全員Unity Test Runnerを使え!爆速のトライ&エラー環境だぞ!
【Unity】TestRunnerで使えるNUnit.Frameworknoアトリビュートの使い方メモ
- 投稿日:2019-04-30T08:29:16+09:00
Rfc2898DeriveBytes と OpenSSL PBKDF2 で相互運用できることを確認した
Rfc2898DeriveBytes と OpenSSL PBKDF2 で相互運用できることを確認した
RFC の規格で相互運用できなかったら詐欺じゃーんの世界だけど、念のため.
Microsoft (R) Roslyn C# Compiler version 2.10.0.0 Loading context from 'CSharpInteractive.rsp'. Type "#help" for more information. > using System.Security.Cryptography; > new Rfc2898DeriveBytes("pass", Encoding.ASCII.GetBytes("saltsalt"), 1000).GetBytes(20) byte[20] { 100, 56, 132, 29, 150, 178, 121, 214, 208, 80, 62, 64, 40, 83, 211, 156, 131, 69, 34, 128 }$ irb irb(main):001:0> require 'openssl' => true irb(main):002:0> OpenSSL::PKCS5.pbkdf2_hmac("pass", "saltsalt", 1000, 20, "sha1").unpack("C*") => [100, 56, 132, 29, 150, 178, 121, 214, 208, 80, 62, 64, 40, 83, 211, 156, 131, 69, 34, 128]おっけー.
一応注意事項はあって、
> new Rfc2898DeriveBytes("pass", Encoding.ASCII.GetBytes("salt"), 1000).GetBytes(20) Salt is not at least eight bytes. + System.Security.Cryptography.Rfc2898DeriveBytes.set_Salt(byte[]) + System.Security.Cryptography.Rfc2898DeriveBytes..ctor(byte[], byte[], int, System.Security.Cryptography.HashAlgorithmName) + System.Security.Cryptography.Rfc2898DeriveBytes..ctor(string, byte[], int)irb(main):003:0> OpenSSL::PKCS5.pbkdf2_hmac("pass", "salt", 1000, 20, "sha1").unpack("C*") => [59, 207, 44, 177, 178, 30, 14, 32, 48, 209, 13, 36, 152, 42, 10, 175, 56, 141, 117, 36]Rfc2898DeriveBytes は規格に則って8バイト未満の salt を弾くけど、OpenSSL は気にせず計算する.









