20190430のC#に関する記事は6件です。

[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-brothers

Stringとstringの違い
大文字のStringを使う場合は、「System名前空間」のusingが必要。
小文字のstringを使う場合は、usingは不要。
https://kuroeveryday.blogspot.com/2014/09/string.html

yield について
https://csharp.keicode.com/basic/yield.php

outとref
https://qiita.com/muro/items/f88b17b5fea3b4537ba7

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityで使うランキング表示用サーバーを作る話

どうも洋梨?です。
ゲームによくある「スコアランキング」ですが、この機能を実装していくまでの話を簡単に書いていきます。
こちらも是非ご覧ください。

環境

テスト環境としてXAMPP
データーベースはMySQL (MariaDB)
サーバーはNode.js
フロント側はUnityで行っています。
image.png

データーベースを構築する

今回構築するデーターベースは

id(プレイヤー のID) ,name (プレイヤー の名前) ,score (プレイヤーの点数) ,date(記録した日時)

を保存するものとします。

image.png
まずデーターベースを構築します。

今回はテストとしてデーターをいくつか追加しておきます。なお、テーブル名は”RANK“としてます。

Node.jsでサーバーを構築

今回フレームワークとして Express を使用します。

なお、サーバーはポート番号:3000で待ち受け、 localhost:3000/Getにアクセスされ、データーの一覧をjson形式で返すものとします。

main.js
const 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);
}

image.png
実行した後、ブラウザなどでアクセスすると動いているのを確認できると思います。

Unityでサーバから情報を受け取る

まずはUnity上でサーバーから受信できるかをテストします。

画面のGETボタンをクリックしたら受信をするようにします。

Test.cs
    public 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);
        }
    }

image.png

取得できている場合、ログに出力されると思います。

デシリアライズし、使える形式にする

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;
}

シリアライズに使うクラス(構造)はこんな感じです。

image.png
サーバーからのリスポンス(JSON)はこのようなデーターです

Test.cs
    public 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データーを表示するように書き換えます。
image.png

成功するとこのように表示されます。

これでUnity上でサーバーから取得した情報が使えるようになりました。

データーベースに情報を登録する

次はUnityからサーバーにスコア(情報)を登録できるようにしていきたいと思います。

リクエスト構造(JSON)

今回サーバーに送信するリクエスト形式は次のようにしました。

JSON { id , action, name , score }
id : ユーザー識別用ID
action : 操作内容(例:追加 = ADD)
name : ユーザー名
score : スコア

リクエストを処理する(サーバー側)

まずはNode.jsでリクエストを処理するためのプログラムを作成します。

今回は追加(ADD)リクエストが来たらとりあえず何も考えずデーターベースに登録するとします。
なお、リクエスト先は localhost:3000/post とします。

main.js
app.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.cs
    public 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();
    }

実行してみるとデーターベースに登録されているのがわかると思います。
image.png
↑ リクエスト送信前と送信後でデーターが追加されているのがわかる

image.png
送信後 /Get でリストを取得すると確かに登録されていることが確認できます。これでUnityからサーバーに登録もできるようになり、ランキング表示機能として使えるようになりました?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityで使うランキング表示用サーバーを作った話

どうも洋梨?です。
ゲームによくある「スコアランキング」ですが、この機能を実装していくまでの話を簡単に書いていきます。
こちらも是非ご覧ください。

環境

テスト環境としてXAMPP
データーベースはMySQL (MariaDB)
サーバーはNode.js
フロント側はUnityで行っています。
image.png

データーベースを構築する

今回構築するデーターベースは

id(プレイヤー のID) ,name (プレイヤー の名前) ,score (プレイヤーの点数) ,date(記録した日時)

を保存するものとします。

image.png
まずデーターベースを構築します。

今回はテストとしてデーターをいくつか追加しておきます。なお、テーブル名は”RANK“としてます。

Node.jsでサーバーを構築

今回フレームワークとして Express を使用します。

なお、サーバーはポート番号:3000で待ち受け、 localhost:3000/Getにアクセスされ、データーの一覧をjson形式で返すものとします。

main.js
const 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);
}

image.png
実行した後、ブラウザなどでアクセスすると動いているのを確認できると思います。

Unityでサーバから情報を受け取る

まずはUnity上でサーバーから受信できるかをテストします。

画面のGETボタンをクリックしたら受信をするようにします。

Test.cs
    public 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);
        }
    }

image.png

取得できている場合、ログに出力されると思います。

デシリアライズし、使える形式にする

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;
}

シリアライズに使うクラス(構造)はこんな感じです。

image.png
サーバーからのリスポンス(JSON)はこのようなデーターです

Test.cs
    public 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データーを表示するように書き換えます。
image.png

成功するとこのように表示されます。

これでUnity上でサーバーから取得した情報が使えるようになりました。

データーベースに情報を登録する

次はUnityからサーバーにスコア(情報)を登録できるようにしていきたいと思います。

リクエスト構造(JSON)

今回サーバーに送信するリクエスト形式は次のようにしました。

JSON { id , action, name , score }
id : ユーザー識別用ID
action : 操作内容(例:追加 = ADD)
name : ユーザー名
score : スコア

リクエストを処理する(サーバー側)

まずはNode.jsでリクエストを処理するためのプログラムを作成します。

今回は追加(ADD)リクエストが来たらとりあえず何も考えずデーターベースに登録するとします。
なお、リクエスト先は localhost:3000/post とします。

main.js
app.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.cs
    public 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();
    }

実行してみるとデーターベースに登録されているのがわかると思います。
image.png
↑ リクエスト送信前と送信後でデーターが追加されているのがわかる

image.png
送信後 /Get でリストを取得すると確かに登録されていることが確認できます。これでUnityからサーバーに登録もできるようになり、ランキング表示機能として使えるようになりました?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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と直接書いてしまっても問題ないかと思います。
burstCount.png
パラメーターから粒子の数を取得したい場合は
上の画像のCountの下の数字を取得してくればいいので
配列初期化時の要素数に_particleSystem.emission.burstCountを与えてあげれば可能です。

あとは_particleSystem.GetParticles(particles)とすることで
指定したParticleSystem内の粒子を全て取得することができます。

Vector3 particleSeedPosition = particles[0].position;

最後にparticlesのindexに先頭である0を指定して
粒子のポジション取得が完了です。

GetParticles

スクリプトリファレンスにも記述ありましたが、
GetParticlesは現時点で生存しているParticleの粒子を取得するので、
Start内で呼び出してしまうとまだ存在していない粒子に対してGet(取得)してしまうことになり、
うまくいきませんでした。

デモ

ParticleAudioSourceAdd.gif

AudioSourceが一緒に移動しているのがわかるかと思います。

前例が少ない、
エラーが出ない、
などなど、深い沼だった...

この沼から出れた瞬間の快感、病みつきになりますね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】テストを全く知らない初心者が勉強に利用したリンク集

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 は気にせず計算する.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む