読者です 読者をやめる 読者になる 読者になる

PaperSloth’s diary

Unity(C#)、UE4(Blueprint/C++)についての記事を書いたり日常のことをつぶやきます。

C/C++からUnityC#引越しガイド01(delegate編)

C# Unity プログラミング C/C++

こんちは!

 

今回はこちらの

Unity 引っ越しガイド | Unreal Engine

を見ていいなーと思ったのでこんな感じの記事を書いてみようと思いました。

 

なので、最後は書ききったらまとめ記事も書こうと思っています。

今回はその第一回目としてdelegateについて紹介させていただきます。

 

前置きが長くなりましたが、こちらが今回のお品書きです。

 ・delegateと関数ポインタの違い
 ・delegateとセットで覚えたいevent
 ・定義済みdelegate(名前正しいかは自信ないです)
 ・C#ラムダ式

 

 ※C/C++C#もにわかですので、間違いがあれば言っていただけるととても助かります('ω')

 

 環境

 ・Visual Studio2013 community

 ・Unity 5.0.0f4 Personal

 

あと、関係ないですが可愛いのでD言語君貼っておきますね・・・

 制作者のらりほまさんからは掲載許可を頂きました。感謝(*‘∀‘)

f:id:PaperSloth:20150603002612j:plain

 

 

 

C#delegateC/C++の関数ポインタの違いについて

 -クラスのメソッドも追加可能

 -複数メソッドを追加可能

 -呼び出し時には格納した順に順次実行される

 -メソッドの代入、追加、削除を自由に行える

 

Example.cpp 

// 関数ポインタの例
#include <iostream>
#include <string>

void Hello(const std::string &str)
{
std::cout << "Hello" << str << std::endl;
}

int main(void)
{
void(*pFunc)(const std::string &str) = Hello;
pFunc("World");
return 0;
}

 

HelloDelegate.cs

using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// delegateへの代入
/// </summary>
public class HelloDelegate: MonoBehaviour {
private delegate void DelegateFunc(string str);

private void Hello(string str)
{
Debug.Log("Hello" + str);
}

void Start () {
DelegateFunc func = Hello;
func("World");
}
}

 

以下変更箇所のみを記載します。

delegateへのクラスメソッドの代入

private class Hoge {
public void Hello(string str)
{
Debug.Log("Hello" + str);
}
}

void Start () {
Hoge hoge = new Hoge();
DelegateFunc func = hoge.Hello;
func("World");

 

delegateへの複数メソッドの追加、削除

private delegate void DelegateFunc();
private class Hoge {
public void Hello()
{
Debug.Log("Hello");
}
public void World()
{
Debug.Log("World");
}
}

void Start () {
Hoge hoge = new Hoge();
DelegateFunc func = null;

func += hoge.Hello;
func += hoge.World;
func();
func -= hoge.Hello;
func -= hoge.World;
}

delegateコワクナイヨーというお話でした。

次はeventについてです。

 

 

C#のevent(C/C++のコールバック関数的なやつ)

 -ローカル変数には使用不可

 -delegateのプロパティ(get/set)みたいなイメージ

 -クラスのメンバーでなければならない

 -同クラスのメソッドからのみ呼び出し可能

 MouseDelegate.cs 

/// <summary>
/// マウスイベントを実行するクラス
/// </summary>
using UnityEngine;
using System.Collections.Generic;

public class MouseDelegate: MonoBehaviour {
public class MouseClick
{
public delegate void MouseDelegate(string str);
public event MouseDelegate m_Event;

public MouseClick() { m_Event = null; }

public void OnClick(string str) {
// 登録した関数呼び出し
m_Event(str);
}
}

private MouseClick m_mouse;
void Start() {
m_mouse = new MouseClick();
// イベント登録
m_mouse.m_Event += (string str) => Debug.Log("MouseClick"); ;
}

void Update() {
if (Input.GetMouseButtonDown(0)) {
m_mouse.OnClick("");
// eventは外部から直接呼び出し不可
// m_mouse.m_Event();
}
}
}

 

・定義済みdelegate

delegateには定義済みdelegateというものがあります。

その中からActionとFuncを紹介します。

他にもPredicate, Comparison, Converterがあります。

 

ActionDelegate

 -パラメータ、戻り値を持たないメソッドカプセル化

 -単一または複数のパラメータを受け取り、戻り値を返さないメソッドカプセル化

 

ActionDelegate.cs

using UnityEngine;
using System.Collections.Generic;

public class ActionDelegate: MonoBehaviour {
private void ActionDelegate() {
Debug.Log("ActionDelegateの実行");
}

private void ActionDelegate(string str) {
Debug.Log(str);
}

void Start() {
System.Action action = ActionDelegate;
action();

System.Action<string> actionParam = ActionDelegate;
actionParam("ActionDelegate(OneParam)を実行");
}
}

 

FuncDelegate

 -単一または複数のパラメータを受け取り、

  第2引数に指定した値を返すメソッドカプセル化

 

FuncDelegate.cs

using UnityEngine;
using System.Collections.Generic;

public class FuncDelegate: MonoBehaviour {
  private string FuncDelegate(string str) {
return str;
}

void Start() {
// Func<T, TResult>
System.Func<string, string> func = FuncDelegate;
Debug.Log(FuncDelegate("Funcを実行"));
}
}

 

 

 

C#ラムダ式(Lambda Expression)

 -delegateを簡潔に記述できる

 -メソッドの記述が不要

 -人によっては読みにくい(らしい)

 -スプラトゥーンみたいなイカ演算子可愛い(疲れてる)

 -(ここ重要)イカちゃんの図 = () =>

 

 

LambdaExample.cs

using UnityEngine;
using System.Collections.Generic;

public class LambdaExample : MonoBehaviour {
private delegate void DelegateVoid();
private delegate void DelegateString(string str);

private DelegateVoid m_void;
private DelegateString m_string;

private void FuncVoid() {
Debug.Log("CallVoid");
}

private void FuncString(string str) {
Debug.Log("Call" + str);
}

void Start() {
// 通常のdelegate
m_void = FuncVoid;
m_void();
m_string = FuncString;
m_string("String");

// ラムダ式
// 一行の場合{ } を省略可
m_void = () => Debug.Log("CallVoid"); ;
m_void();

// この方が見やすい場合が多い
m_string = (string str) =>
{
Debug.Log("Call" + str);
};
m_string("String");
}
}

 

 

 

第一回目から結構ずらずらと長く書きました・・・

実際に書いているコードはなるべくシンプルになるようにしたんですが、

私の実力ではこの程度です

 

わかりにくいねー('Д')

 

 

今後はCoroutine, yield, abstract, interface, foreach, Generics, Collectionを書くかもです。

予習して教えてくれてもいいんですよ('ω')

 

今回はこんな感じでおわりまーす

 

ではまた