HOME /

SHARE THE MAKING.

つくる楽しさも、
シェアしよう。

開発の途中で見つけた、役に立つ資料とコード。
ゲームづくりのヒントになったら、うれしいです。

LINKS THAT HELPED.

参考サイト

FROM MY TOOLBOX.

Script紹介

開発時に使った実装例です。SDKやUnityのバージョンによって、調整が必要な場合があります。

01GoogleBannerAds+
C#ダウンロード ↓
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds.Api;
public class GoogleBannerAds : MonoBehaviour
{
    private BannerView bannerView;
    public void Start()
    {
        // Google AdMob Initial
        MobileAds.Initialize(initStatus => { });
        this.RequestBanner();
    }
    private void RequestBanner()
    {
#if UNITY_ANDROID
    string adUnitId = "ca-app-pub-3940256099942544/6300978111"; // テスト用広告ユニットID
#elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/2934735716"; // テスト用広告ユニットID[ca-app-pub-3940256099942544/2934735716] 
#else
    string adUnitId = "unexpected_platform";
#endif
        // Create a 320x50 banner at the bottom of the screen.
        this.bannerView = new BannerView(adUnitId, AdSize.Banner, AdPosition.Bottom);
        // Create an empty ad request.
        AdRequest request = new AdRequest();
        // Load the banner with the request.
        bannerView.LoadAd(request);
    }
}
02GoogleInterstitialAds+
C#ダウンロード ↓
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class GoogleInterstitialAds : MonoBehaviour
{
    // これらの広告ユニットは、常にテスト広告を配信するように設定されています。
#if UNITY_EDITOR
    private string _adUnitId = "ca-app-pub-3940256099942544/4411468910";//<-テストId[変えないように]
#elif UNITY_IOS
    private string _adUnitId = "ca-app-pub-3940256099942544/4411468910";// !!間違ってテストで本番Id実行しないように!! -> 本番Id"" //
#endif
    private InterstitialAd interstitialAd;
    /// <summary>
    /// Loads the interstitial ad.
    /// </summary>
    public void Start()
    {
        // Google Mobile Ads SDK を初期化します。バナーかインタースティシャルどちらかで初期化すればよい。
        MobileAds.Initialize((InitializationStatus initStatus) =>
        {
            // このコールバックは、MobileAds SDK が初期化されると呼び出されます。
        });
        LoadInterstitialAd();
        Debug.Log("広告をロード");
    }
    public void LoadInterstitialAd()
    {
        // 既にロードされている広告があれば破棄します。
        if (interstitialAd != null)
        {
            interstitialAd.Destroy();
            interstitialAd = null;
        }
        Debug.Log("インタースティシャル広告を読み込んでいます。");
        // 広告を読み込むために使用するリクエストを作成します。
        var adRequest = new AdRequest();
        adRequest.Keywords.Add("unity-admob-sample");
        // 広告を読み込むリクエストを送信します。
        InterstitialAd.Load(_adUnitId, adRequest,
            (InterstitialAd ad, LoadAdError error) =>
            {
                // エラーが null でない場合、ロード リクエストは失敗しました。
                if (error != null || ad == null)
                {
                    Debug.LogError("インタースティシャル広告が広告を読み込めませんでした " +
                                   "with error : " + error);
                    return;
                }
                Debug.Log("レスポンスを伴うインタースティシャル広告が読み込まれる : "
                          + ad.GetResponseInfo());
                interstitialAd = ad;
                RegisterEventHandlers(interstitialAd);
                Debug.Log("イベントハンドラーの登録");
                RegisterReloadHandler(interstitialAd);
                Debug.Log("ロードハンドラーの登録");
            });
    }
    /// <summary>
    /// Shows the interstitial ad.
    /// </summary>
    public void ShowAd() // この関数を呼び出してやればよい。
    {
        if (interstitialAd != null && interstitialAd.CanShowAd())
        {
            Debug.Log("インタースティシャル広告を表示しています。");
            interstitialAd.Show();
        }
        else
        {
            Debug.LogError("インタースティシャル広告はまだ準備ができていません。");
        }
    }
    //イベントハンドラーの登録
    private void RegisterEventHandlers(InterstitialAd ad)
    {
        // 広告が収益を上げたと推定される場合に発生します。
        ad.OnAdPaid += (AdValue adValue) =>
        {
            Debug.Log(String.Format("インタースティシャル広告には {0} {1} が支払われました。",
                adValue.Value,
                adValue.CurrencyCode));
        };
        // 広告のインプレッションが記録されるときに発生します。
        ad.OnAdImpressionRecorded += () =>
        {
            Debug.Log("インタースティシャル広告がインプレッションを記録しました。");
        };
        // 広告のクリックが記録されたときに発生します。
        ad.OnAdClicked += () =>
        {
            Debug.Log("インタースティシャル広告がクリックされました。");
        };
        // 広告が全画面コンテンツを開いたときに発生します。
        ad.OnAdFullScreenContentOpened += () =>
        {
            Debug.Log("インタースティシャル広告の全画面コンテンツが開きました。");
        };
        // 広告が全画面コンテンツを閉じたときに発生します。
        ad.OnAdFullScreenContentClosed += () =>
        {
            Debug.Log("インタースティシャル広告の全画面コンテンツが閉じられました。");
        };
        // 広告が全画面コンテンツを開けなかった場合に発生します。
        ad.OnAdFullScreenContentFailed += (AdError error) =>
        {
            Debug.LogError("インタースティシャル広告が全画面コンテンツを開けませんでした " +
                           "with error : " + error);
        };
    }
    private void RegisterReloadHandler(InterstitialAd ad)
    {
        // 広告が全画面コンテンツを閉じたときに発生します。
        ad.OnAdFullScreenContentClosed += () =>
        {
            Debug.Log("インタースティシャル広告の全画面コンテンツが閉じられました。");
            // できるだけ早く別の広告を表示できるよう、広告をリロードしてください。
            LoadInterstitialAd();
        };
        // 広告が全画面コンテンツを開けなかった場合に発生します。
        ad.OnAdFullScreenContentFailed += (AdError error) =>
        {
            Debug.LogError("インタースティシャル広告が全画面コンテンツを開けませんでした " +
                           "with error : " + error);
            // できるだけ早く別の広告を表示できるよう、広告をリロードしてください。
            LoadInterstitialAd();
        };
    }
}
03PlayFabLogin+
C#ダウンロード ↓
using System.Text;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;
/// <summary>
/// PlayFabのログイン処理を行うクラス
/// </summary>
public class PlayFabLogin : MonoBehaviour {
 //アカウントを作成するか
 private bool _shouldCreateAccount;
 //ログイン時に使うID
 private string _customID;
 //=================================================================================
 //ログイン処理
 //=================================================================================
 public void Start() {
   Login();
 }
 //ログイン実行
 private void Login() {
   _customID = LoadCustomID();
   var request = new LoginWithCustomIDRequest { CustomId = _customID,  CreateAccount = _shouldCreateAccount};
   PlayFabClientAPI.LoginWithCustomID(request, OnLoginSuccess, OnLoginFailure);
 }
 //ログイン成功
 private void OnLoginSuccess(LoginResult result){
   //アカウントを作成しようとしたのに、IDが既に使われていて、出来なかった場合
   if (_shouldCreateAccount && !result.NewlyCreated) {
     Debug.LogWarning($"CustomId : {_customID} は既に使われています。");
     Login();//ログインしなおし
     return;
   }
  
   //アカウント作成時にIDを保存
   if (result.NewlyCreated) {
     SaveCustomID();
   }
   Debug.Log($"PlayFabのログインに成功\nPlayFabId : {result.PlayFabId}, CustomId : {_customID}\nアカウントを作成したか : {result.NewlyCreated}");
 }
 //ログイン失敗
 private void OnLoginFailure(PlayFabError error){
   Debug.LogError($"PlayFabのログインに失敗\n{error.GenerateErrorReport()}");
 }
 //=================================================================================
 //カスタムIDの取得
 //=================================================================================
 //IDを保存する時のKEY
 private static readonly string CUSTOM_ID_SAVE_KEY = "CUSTOM_ID_SAVE_KEY";
 //IDを取得
 private string LoadCustomID() {
   //IDを取得
   string id = PlayerPrefs.GetString(CUSTOM_ID_SAVE_KEY);
   //保存されていなければ新規生成
   _shouldCreateAccount = string.IsNullOrEmpty(id);
   return _shouldCreateAccount ? GenerateCustomID() : id;
 }
 //IDの保存
 private void SaveCustomID() {
   PlayerPrefs.SetString(CUSTOM_ID_SAVE_KEY, _customID);
 }
 //=================================================================================
 //カスタムIDの生成
 //=================================================================================
 //IDに使用する文字
 private static readonly string ID_CHARACTERS = "0123456789abcdefghijklmnopqrstuvwxyz";
 //IDを生成する
 private string GenerateCustomID() {
   int idLength = 32;//IDの長さ
   StringBuilder stringBuilder = new StringBuilder(idLength);
   var random = new System.Random();
   //ランダムにIDを生成
   for (int i = 0; i < idLength; i++){
     stringBuilder.Append(ID_CHARACTERS[random.Next(ID_CHARACTERS.Length)]);
   }
   return stringBuilder.ToString();
 }
}
04PlayFabRename+
C#ダウンロード ↓
using System.Collections.Generic;
using System.Collections;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;
using TMPro;
/// <summary>
/// ユーザー名変更
/// </summary>
public class PlayFabRename : MonoBehaviour
{
    [SerializeField] TextMeshProUGUI _nameText = default;
    //=================================================================================
    //ユーザ名
    //=================================================================================
    public void matu_void()
    {
        StartCoroutine(matu());
    }
    IEnumerator matu()
    {
        yield return new WaitForSeconds(0.1f);//テキスト待ち
        UpdateUserName();
    }
    /// <summary>
    /// ユーザ名を更新する
    /// </summary>
    public void UpdateUserName()
    {
        //ユーザ名を指定して、UpdateUserTitleDisplayNameRequestのインスタンスを生成
        var request = new UpdateUserTitleDisplayNameRequest
        {
            DisplayName = _nameText.text + Random.Range(0, 9).ToString() + Random.Range(0, 9).ToString()
        };
        //ユーザ名の更新
        Debug.Log($"ユーザ名の更新開始");
        PlayFabClientAPI.UpdateUserTitleDisplayName(request, OnUpdateUserNameSuccess, OnUpdateUserNameFailure);
    }
    //ユーザ名の更新成功
    private void OnUpdateUserNameSuccess(UpdateUserTitleDisplayNameResult result)
    {
        //result.DisplayNameに更新した後のユーザ名が入ってる
        Debug.Log($"ユーザ名の更新が成功しました : {result.DisplayName}");
    }
    //ユーザ名の更新失敗
    private void OnUpdateUserNameFailure(PlayFabError error)
    {
        Debug.LogError($"ユーザ名の更新に失敗しました\n{error.GenerateErrorReport()}");
    }
}
05PlayFabSend+
C#ダウンロード ↓
using System.Collections.Generic;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// ランキング送信
/// </summary>
public class PlayFabSend : MonoBehaviour {
public int sendInt;
  //=================================================================================
  //スコア
  //=================================================================================
  /// <summary>
  /// スコア(統計情報)を更新する
  /// </summary>
  public void UpdatePlayerStatistics() {
    //UpdatePlayerStatisticsRequestのインスタンスを生成
    var request = new UpdatePlayerStatisticsRequest{
      Statistics = new List<StatisticUpdate>{
        new StatisticUpdate{
          StatisticName = "ランキングサンプル",   //ランキング名(統計情報名)
          Value = sendInt, //スコア(int)
        }
      }
    };
    //ユーザ名の更新
    Debug.Log($"スコア(統計情報)の更新開始");
    PlayFabClientAPI.UpdatePlayerStatistics(request, OnUpdatePlayerStatisticsSuccess, OnUpdatePlayerStatisticsFailure);
  }
  
  //スコア(統計情報)の更新成功
  private void OnUpdatePlayerStatisticsSuccess(UpdatePlayerStatisticsResult result){
    Debug.Log($"スコア(統計情報)の更新が成功しました");
  }
  //スコア(統計情報)の更新失敗
  private void OnUpdatePlayerStatisticsFailure(PlayFabError error){
    Debug.LogError($"スコア(統計情報)更新に失敗しました\n{error.GenerateErrorReport()}");
  }
}
06PlayFabAcquisition+
C#ダウンロード ↓
using System.Collections.Generic;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;
using TMPro;
/// <summary>
/// ランキング取得
/// </summary>
public class PlayFabAcquisition : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI _rankingText = default;
    //=================================================================================
    //ランキング取得
    //=================================================================================
    /// <summary>
    /// ランキング(リーダーボード)を取得
    /// </summary>
    public void GetLeaderboard()
    {
        //GetLeaderboardRequestのインスタンスを生成
        var request = new GetLeaderboardRequest
        {
            StatisticName = "ランキングサンプル", //ランキング名(統計情報名)
            StartPosition = 0,                 //何位以降のランキングを取得するか
            MaxResultsCount = 10                  //ランキングデータを何件取得するか(最大100)
        };
        //ランキング(リーダーボード)を取得
        Debug.Log($"ランキング(リーダーボード)の取得開始");
        PlayFabClientAPI.GetLeaderboard(request, OnGetLeaderboardSuccess, OnGetLeaderboardFailure);
    }
    //ランキング(リーダーボード)の取得成功
    private void OnGetLeaderboardSuccess(GetLeaderboardResult result)
    {
        Debug.Log($"ランキング(リーダーボード)の取得に成功しました");
        //result.Leaderboardに各順位の情報(PlayerLeaderboardEntry)が入っている
        _rankingText.text = "";
        foreach (var entry in result.Leaderboard)
        {
            _rankingText.text += $"{entry.Position + 1}位  名前{entry.DisplayName}  スコア{entry.StatValue}\n";
        }
    }
    //ランキング(リーダーボード)の取得失敗
    private void OnGetLeaderboardFailure(PlayFabError error)
    {
        Debug.LogError($"ランキング(リーダーボード)の取得に失敗しました\n{error.GenerateErrorReport()}");
    }
}
07VoiceRecognitionManager(Swift,Xcode)+
Swiftダウンロード ↓
import SwiftUI
import Speech
import AVFoundation
@_cdecl("startRecordingFunc")
public func startRecordingFunc() {
    let voiceRecognitionManager = VoiceRecognitionManager.shared
    voiceRecognitionManager.startRecording()
}
@_cdecl("stopRecordingFunc")
public func stopRecordingFunc() {
    let voiceRecognitionManager = VoiceRecognitionManager.shared
    voiceRecognitionManager.stopRecording()
}
// UnityのC#側で定義されたコールバックをSwiftから呼び出す
@_cdecl("OnRecognizedText")
public func OnRecognizedText(_ recognizedText: UnsafePointer<CChar>) {
    // Unityに認識結果を送る
    let unityCallback = VoiceRecognitionManager.unityCallback
    unityCallback?(String(cString: recognizedText))
}
class VoiceRecognitionManager {
    static let shared = VoiceRecognitionManager()
    
    private var audioEngine = AVAudioEngine()
    private var speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "it-IT"))
    private var request = SFSpeechAudioBufferRecognitionRequest()
    private var task: SFSpeechRecognitionTask?
    
    public var recognizedText: String = "話してください..."
    
    // Unityのコールバックを保持するためのプロパティ
    static var unityCallback: ((String) -> Void)?
    
    public func startRecording() {
        SFSpeechRecognizer.requestAuthorization { authStatus in
            if authStatus == .authorized {
                DispatchQueue.main.async {
                    self.startAudioEngine()
                }
            } else {
                DispatchQueue.main.async {
                    if #available(iOS 13.0, *) {
                        self.recognizedText = "音声認識が許可されていません。"
                    }
                }
            }
        }
    }
    
    private func startAudioEngine() {
        let inputNode = audioEngine.inputNode
        let recordingFormat = inputNode.outputFormat(forBus: 0)
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
            self.request.append(buffer)
        }
        
        audioEngine.prepare()
        
        do {
            try audioEngine.start()
            if #available(iOS 13.0, *) {
                recognizedText = "聞き取っています..."
            }
        } catch {
            if #available(iOS 13.0, *) {
                recognizedText = "オーディオエンジンの起動に失敗しました。"
            }
        }
        
        request.shouldReportPartialResults = true
        if #available(iOS 13.0, *) {
            request.requiresOnDeviceRecognition = true
        }
        
        task = speechRecognizer?.recognitionTask(with: request, resultHandler: { result, error in
            if let result = result {
                DispatchQueue.main.async {
                    // 認識されたテキストを `recognizedText` に代入
                    self.recognizedText = result.bestTranscription.formattedString
                    
                    // UnityのC#側のコールバックを呼び出す
                    if let unityCallback = VoiceRecognitionManager.unityCallback {
                        unityCallback(self.recognizedText)
                    }
                }
            }
            
            if error != nil {
                self.audioEngine.stop()
                inputNode.removeTap(onBus: 0)
            }
        })
    }
    
    func stopRecording() {
        audioEngine.stop()
        request.endAudio()
        task?.cancel()
    }
}
08VoiceRecognitionPlugin(Unity)+
C#ダウンロード ↓
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class VoiceRecognitionPlugin : MonoBehaviour
{
    public delegate void VoiceRecognitionCallback(string recognizedText);
    public static VoiceRecognitionCallback onRecognizedText;
    // iOS側の関数を呼び出すためのインポート
    [DllImport("__Internal")]
    private static extern void startRecordingFunc();
    [DllImport("__Internal")]
    private static extern void stopRecordingFunc();
    // UnityからiOSの音声認識を開始
    public void StartRecording()
    {
        startRecordingFunc();
    }
    // UnityからiOSの音声認識を停止
    public void StopRecording()
    {
        stopRecordingFunc();
    }
    [AOT.MonoPInvokeCallback(typeof(VoiceRecognitionCallback))]
    public static void OnRecognizedText(string recognizedText)
    {
        Debug.Log("音声認識結果: " + recognizedText);
        // ここで、音声認識結果をゲーム内で使う処理を行う
        if (onRecognizedText != null)
        {
            onRecognizedText.Invoke(recognizedText);  
        }
    }
}