20210428のC#に関する記事は7件です。

#csharp #programming #dotnetframework DataGridViewの編集不可(=ReadOnly)のバグの対処方法

本内容を利用した場合の一切の責任を私は負いません。 再現条件が稀で、影響も大きくなく、自分のバージョンが古くて今は起こらないかもだけど一応書いておく。 バージョン  .NET Framework 3.7.2  Visual Studio Community 2015 再現手順 Windowsフォームアプリケーションのプロジェクトを作ってDataGridViewを配置する。 デザイナ上のDataGridViewの編集有効チェックを外れにする。 デザイナ上でチェックボックスやテキストボックスの列を追加する。 ビルドする。(これは関係あるかは不明。) デザイナ上のDataGridViewの編集有効チェックを入りにする。 Formのコンストラクタ等に適当に行を追加する処理を入れる。 ビルドして実行する。 編集有効設定にも関わらず、編集できない。 DataGridViewや各列のReadOnlyプロパティもプロパティウィンドウ上ではFalseになっている。 対処方法 いろいろ方法はあると思う。 自分がやったのは、改めて列を追加し直した。(一旦列を消す。) DataGridViewを配置し直しても対処できると思う。 うろ覚えだが、見た目FalseになってるReadOnlyプロパティを一旦Trueにして保存し、またFalseに戻して更新させる方法でも対処できたような気もする。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gtk3アプリのTreeViewの表示

Gtk3のTreeViewの表示 GtkSharpチュートリアルに書かれているサンプルをコピペするだけでTreeViewを表示できます GtkSharp TreeView Tutorial Gladeの編集 GladeにtreeViewを追加をします 不要なコントロールは削除しました TreeViewにIdのところに名前をつけます TreeVieIDを定義します。 Gtk3Sharpテンプレートにあった余分なイベントハンドラーは削除しました。 using System; using Gtk; using UI = Gtk.Builder.ObjectAttribute; namespace treeViewGtkApplication { class MainWindow : Window { [UI] private TreeView _treeView1 = null; public MainWindow() : this(new Builder("MainWindow.glade")) { } private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("MainWindow")) { builder.Autoconnect(this); _mkTreeView(); } void _mkTreeView() { Gtk.TreeViewColumn artistColumn = new Gtk.TreeViewColumn (); artistColumn.Title = "Artist"; // アーティスト名を表示するテキストセルを作成する Gtk.CellRendererText artistNameCell = new Gtk.CellRendererText (); // セルを列に追加する artistColumn.PackStart (artistNameCell, true); // 曲名の列を作る Gtk.TreeViewColumn songColumn = new Gtk.TreeViewColumn (); songColumn.Title = "曲名"; // 曲名の列にも同じことをする Gtk.CellRendererText songTitleCell = new Gtk.CellRendererText (); songColumn.PackStart (songTitleCell, true); // TreeViewにカラムを追加する _treeView1.AppendColumn (artistColumn); _treeView1.AppendColumn (songColumn); // モデル内のどのアイテムを表示するかをセルレンダラーに伝える artistColumn.AddAttribute (artistNameCell, "text", 0); songColumn.AddAttribute (songTitleCell, "text", 1); // アーティスト名と曲名の2つの文字列を保持するモデルを作成します。 Gtk.ListStore musicListStore = new Gtk.ListStore (typeof (string), typeof (string)); // ストアにデータを追加します。 musicListStore.AppendValues ("Garbage", "Dog New Tricks"); // TreeViewにモデルを割り当てる _treeView1.Model = musicListStore; } } } チュートリアルのサンプルの書き換える必要があります。 Mono Gtk.TreeModel ↓ GTK3 Gtk.ITreeModel Modelを使った表示の仕方 チュートリアルに書かれている内容をコピペで表示できました。 using System; using System.Collections.Generic; using Gtk; using UI = Gtk.Builder.ObjectAttribute; namespace treeView2Application { class MainWindow : Window { [UI] private TreeView _treeView1 = null; List<Song> songs; public MainWindow() : this(new Builder("MainWindow.glade")) { } private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("MainWindow")) { builder.Autoconnect(this); _mkTreeView(); } void _mkTreeView() { songs = new List<Song>(); songs.Add (new Song ("Dancing DJs vs. Roxette", "Fading Like a Flower")); songs.Add (new Song ("Xaiver", "Give me the night")); songs.Add (new Song ("Daft Punk", "Technologic")); Gtk.TreeViewColumn artistColumn = new Gtk.TreeViewColumn (); artistColumn.Title = "Artist"; Gtk.CellRendererText artistNameCell = new Gtk.CellRendererText (); artistColumn.PackStart (artistNameCell, true); Gtk.TreeViewColumn songColumn = new Gtk.TreeViewColumn (); songColumn.Title = "Song Title"; Gtk.CellRendererText songTitleCell = new Gtk.CellRendererText (); songColumn.PackStart (songTitleCell, true); _treeView1.AppendColumn (artistColumn); _treeView1.AppendColumn (songColumn); Gtk.ListStore musicListStore = new Gtk.ListStore (typeof (Song)); foreach (Song song in songs) { musicListStore.AppendValues (song); } artistColumn.SetCellDataFunc (artistNameCell, new Gtk.TreeCellDataFunc (RenderArtistName)); songColumn.SetCellDataFunc (songTitleCell, new Gtk.TreeCellDataFunc (RenderSongTitle)); _treeView1.Model = musicListStore; } private void RenderArtistName (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter) { Song song = (Song) model.GetValue (iter, 0); if (song.Artist.StartsWith ("X") == true) { (cell as Gtk.CellRendererText).Foreground = "red"; } else { (cell as Gtk.CellRendererText).Foreground = "darkgreen"; } (cell as Gtk.CellRendererText).Text = song.Artist; } private void RenderSongTitle (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter) { Song song = (Song) model.GetValue (iter, 0); (cell as Gtk.CellRendererText).Text = song.Title; } } public class Song { public Song (string artist, string title) { this.Artist = artist; this.Title = title; } public string Artist; public string Title; } } 課題 レンダー用の関数を毎回書かないといけなく面倒 SetCellDataFunc関数を毎回書かないようにしたい。 Gtk3アプリのTreeViewの表示の簡略化に続く
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity3D】Rayを使って壁越しにプレイヤーを検知しない敵を作ってみる

はじめに Unityの有料アセットであるBehavior Designer でプレイヤーを検知する敵を作っていましたが、ジャンプしている間は検知してくれなかったので、壁がないときにのみプレイヤーを検知する処理を勉強も兼ねて作ってみました。 ※Unityのバージョンは2019.4.18f1を使用しています。 Ray について Unityの機能の中にRayというものがあります。 これは、指定した位置と方向から光線を飛ばす機能で、光線に当たったオブジェクトの情報を取得したり衝突判定を行うことができます。Rayの当たり判定はRaycastという関数で調べることができ、RaycastHitという構造体にRayと接触したオブジェクトの情報が格納されます。 実装の手順 プレイヤーの座標の取得 敵の位置からプレイヤーの位置へRayを飛ばす 最初にRayが接触したオブジェクトを調べる という手順で進めていきます。 プレイヤーの座標の取得 まず、プレイヤーの座標を取得するために、OnTriggerStay()でコライダーと接触したオブジェクトを取得します。その後、コライダーからタグを調べて、"Player"という名前のタグがついていれば、そのオブジェクトの座標をプレイヤーの座標として利用します。 プレイヤーの座標を取得する他のやり方としては、Find()でプレイヤーのオブジェクトを見つけたり、public変数などでインスペクターにオブジェクトを直接入れる方法でも良いと思います。 敵の位置からプレイヤーの位置へRayを飛ばす Rayを飛ばす位置については敵の視点となる位置(transform.position)を指定するだけです。方向を決めるためには、Rayを飛ばす先(プレイヤーの座標)から、Rayを飛ばす元(敵の座標)を引いて正規化する必要があります(参考:ひとつのオブジェクトから別のオブジェクトへの向きと距離)。 Rayを飛ばす位置と方向が決まったらnewで新しいRayを作成します。 最初にRayが接触したオブジェクトを調べる Raycastを使う方法とRaycastAllを使う方法があります。 Raycastを使う方法 Raycastは、「Rayがオブジェクトに当たったかどうか」というbool値を返します。また、Rayがオブジェクトに当たった場合は、out修飾子を用いることでRayが当たったオブジェクト(RaycastHit)を取得することができます。複数のオブジェクトにRayが当たった場合は、RaycastHitには最初に当たったオブジェクトが格納されます。 よって、RaycastHitに入ったオブジェクトを調べ、それがプレイヤーオブジェクトだった場合は、敵とプレイヤーとの間に物体がないということになるので「プレイヤーを見つけた」と判断します。 RaycastAllを使う方法 Raycastが「Rayがオブジェクトに当たったかどうか」のbool値を返すのに対して、RaycastAllは「Ray がヒットしたオブジェクト(RaycastHit)全てのリスト」を返す関数です。そこでLINQのFirst()メソッドを使ってRaycastAllの最初の要素を調べ、それがプレイヤーだった場合に「プレイヤーを発見した」という判定を行うようにすると、壁がないときにのみプレイヤーを検知するようになります。 ソースコード Raycastを使う方法で記述しています。RaycastAllを使う方法も後述しています。 using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyView : MonoBehaviour { Ray ray; RaycastHit hit; Vector3 direction; // Rayを飛ばす方向 float distance = 10; // Rayを飛ばす距離 private void OnTriggerStay(Collider other) { if (other.CompareTag("Player")) { // Rayを飛ばす方向を計算 Vector3 temp = other.transform.position - transform.position; direction = temp.normalized; ray = new Ray(transform.position, direction); // Rayを飛ばす Debug.DrawRay(ray.origin, ray.direction * distance, Color.red); // Rayをシーン上に描画 // Rayが最初に当たった物体を調べる if (Physics.Raycast(ray.origin, ray.direction * distance, out hit)) { if (hit.collider.CompareTag("Player")) { Debug.Log("プレイヤー発見"); } else { Debug.Log("プレイヤーとの間に壁がある"); } } } } } RayCastAllを使う場合 基本的には上記のスクリプトと同じなので、変更点だけを記載します。 LINQを使うためのusingディレクティブ using System.Linq; を先頭に書いておき、OnTriggerStayの中の if (Physics.Raycast(ray.origin, ray.direction * distance, out hit)) を消して hit = Physics.RaycastAll(ray).First(); を書くと同じように動作します。 プロジェクトの設定 簡単なプロジェクトを作って動作確認をしました。 床をPlane, 壁(青い直方体)と敵(緑の立方体)をCube, プレイヤー(赤いカプセル)をCapsuleで作成しました。 また、Rayを飛ばす際にプレイヤーより先に床や敵自身のオブジェクトにRayが当たると正しく判定されないことがあるので、これら二つのオブジェクトのLayerを"Ignore Raycast"に変更しました。LayerMaskの設定は、デフォルトでは"Ignore Raycast"に指定されたものをRayの接触判定の対象外とします。Raycast内でLayerMaskを指定する方法もあるようです。 プレイヤーオブジェクトの設定 プレイヤーオブジェクトは、タグを"Player"としておき、子要素にMainCameraを持たせます。また、矢印キーで移動できるようにスクリプトも書いてアタッチしておきます。 参考までにプレイヤーのスクリプトも載せておきます。 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { [SerializeField] private float speed = 0.1f; void Update() { if (Input.GetKey(KeyCode.UpArrow)) { transform.position += Vector3.forward * speed; } if (Input.GetKey(KeyCode.LeftArrow)) { transform.position += Vector3.left * speed; } if (Input.GetKey(KeyCode.DownArrow)) { transform.position += Vector3.back * speed; } if (Input.GetKey(KeyCode.RightArrow)) { transform.position += Vector3.right * speed; } } } 敵オブジェクトの設定 敵オブジェクトは、子要素に空のゲームオブジェクトを持たせて、そこに視界の範囲となるコライダーと、EnemyViewスクリプト(上記のスクリプト)をアタッチします。 コライダーは3Dで使えるものであれば何でもよいと思いますが、今回は敵の視界を表すので円錐のような形のコライダーを使いたいと思い、コーンコライダーというアセットをお借りしました。使い方はこちらの記事などで紹介されています。 動作確認 左がシーンで右がゲーム画面です。 プレイヤーがコライダー内に入ったときに、壁があるときは壁との接触を、壁がないときはプレイヤーとの接触を取れていることが確認できました。 おわりに 今回は、Rayを使って壁越しにプレイヤーを検知しない方法を書いてみました。 記事の作成自体初めてで、読みづらかったり分かりにくい部分もあったかもしれません。質問等ございましたらコメントの方でお願いします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UNITYの鏡面反射を使ってみる

はじめに UNITYで風景的なものを作っているのですが、鏡面反射というものがあるのを知ったので使ってみました 使用した環境 パソコン:Acer AS5750 Core(R) i3 2310M メモリ8GB Win10 UNITY:2018.4.34f1 準備 ↓元となる風景は下記のような住宅地で、カーブミラーに鏡面効果を設定してみます (赤マルで囲った部分がカーブミラーです) 作業手順 ↓現在のカーブミラーのマテリアルは、Metallic:0.76、Smoothness:0.68というアルミニウムっぽい設定にしてありますが、何も反射していません ↓ミラー部分のマテリアルを、Metallic:1、Smoothness:1に変更し、[Reflections]をチェックしておきます ↓これでミラーが光沢のある金属面になります さらに、ヒエラルキーのミラーのオブジェクトの場所で右クリックし、[Light]-[Reflection Probe]を選択し、反射させるための機能を追加します ↓現在[Baked]になっている[Type]を、それぞれ下記の画像のように変更します つづいて[Box Projection]をチェックし、[Box Size]を調整します 私の場合、X、Y、Zの値を、それぞれ[10、10、10]から[1、2、1.2]に変更するといい感じになりました [Resolution]も、128から512に変更します 確認してみます ↓[Game]タブで確認してみます ↓丁字路のカーブミラーも同様の修正でこんな感じです プレファブに書き戻し ↓画面左下のカーブミラーだけ鏡面効果を設定したので、右上の赤マルで囲ったカーブミラーはまだ何も反射していません インスペクタのプレファブから、[Overrides]-[Apply All]を実行して、プレファブを更新し、他のオブジェクトにも同じ効果を設定します [Apply All]は影響範囲が広いので、十分確認してから実行してください ↓右上のミラーにも反映されました! さいごに 第二世代のCore i3では、さすがにUNITYは重い印象です クロックが高いのがいいのか?、コア数が多いのがいいのか?、それともGPUの性能が高いものを選ぶべきか? どれが一番効果的なんでしょう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#)】Google Cloud Speech-to-TextをUnityで使用できるGoogle Cloud Speech Recognitionの使い方

はじめに UnityからGoogle Cloud Speech-to-Textを使用する方法をメモします。 OculusQuestでも問題なく動作しました。 Google Cloud Speech-to-Text Googleの提供する音声認識APIです。 下記リンクより登録に進みAPIキーを取得します。 【参考リンク】:Speech-to-Text 登録後、下記ダッシュボードの画面からAPIキーを取得可能です。 料金は従量課金制ですが、1月当り60分までは無料で使えるようです。(精度の検証でしゃべりまくってたら42円請求されてしまいました。) こちらのAPIを使うには少し複雑で、ただ、APIをUnityから叩けばよいという訳ではありません。 かといっていろいろと面倒なことを自前で実装するのも億劫なので、 今回はアセットを使いました。 下記のページでも紹介されている、Google Cloud Speech Recognitionを使用しました。 【参考リンク】:【Unity】自分の声をテキスト化する方法【Google Cloud Speech Recognition 】 バージョン 念のため使ったライブラリ等のバージョンも書いときます。 Unity 2019.4.8f1 UniTask.2.2.4 UniRx 7.1.0 Google Cloud Speech Recognition 4.1.2 準備 アセットをプロジェクトにインポートしたら任意のシーンのヒエラルキーに 適当なオブジェクトを作って下記のように設定します。APIキーは先ほど取得したものです。 GoogleSpeechTestは後述のサンプルコードです。 コード Unityから使用するサンプルです。 using FrostweepGames.Plugins.GoogleCloud.SpeechRecognition; using UniRx; using UniRx.Triggers; using UnityEngine; using UnityEngine.UI; /// <summary> /// Google音声認識テスト /// </summary> public class GoogleSpeechTest : MonoBehaviour { [SerializeField] private Button recButton; [SerializeField] Text resultText; private GCSpeechRecognition _speechRecognition; void Start() { _speechRecognition = GCSpeechRecognition.Instance; _speechRecognition.FinishedRecordEvent += OnFinishedRecordEvent; _speechRecognition.RecognizeSuccessEvent += OnRecognizeSuccessEvent; if (_speechRecognition.HasConnectedMicrophoneDevices()) { _speechRecognition.SetMicrophoneDevice(_speechRecognition.GetMicrophoneDevices()[0]); } recButton.OnPointerDownAsObservable() .Subscribe(_ => _speechRecognition.StartRecord(false)).AddTo(this); recButton.OnPointerUpAsObservable() .Subscribe(_ => _speechRecognition.StopRecord()).AddTo(this); } private void OnDestroy() { _speechRecognition.FinishedRecordEvent -= OnFinishedRecordEvent; _speechRecognition.RecognizeSuccessEvent -= OnRecognizeSuccessEvent; } /// <summary> /// 音声認識成功時のコールバックイベント /// </summary> /// <param name="recognitionResponse">認識結果のレスポンス</param> private void OnRecognizeSuccessEvent(RecognitionResponse recognitionResponse) { string r = ""; foreach (var result in recognitionResponse.results) { foreach (var alternative in result.alternatives) { if (recognitionResponse.results[0].alternatives[0] != alternative) { r = alternative.transcript; } } } resultText.text = r; } /// <summary> /// 録音終了時のコールバックイベント /// </summary> /// <param name="clip">音声クリップ</param> /// <param name="raw">生データ</param> private void OnFinishedRecordEvent(AudioClip clip, float[] raw) { if (clip == null) return; RecognitionConfig config = RecognitionConfig.GetDefault(); config.languageCode = Enumerators.LanguageCode.ja_JP.Parse(); config.audioChannelCount = clip.channels; GeneralRecognitionRequest recognitionRequest = new GeneralRecognitionRequest() { audio = new RecognitionAudioContent() { content = raw.ToBase64() }, config = config }; _speechRecognition.Recognize(recognitionRequest); } } デモ 下記のように動作します。若干レスポンスが遅いです。送信するAudioデータの容量に比例して遅くなる?ようです。 pic.twitter.com/6bjyZGlG6y— KENTO⚽️XRエンジニア?Shader100記事マラソン挑戦中30/100 (@okprogramming) April 24, 2021 おわりに 音声データをストリームしながらリアルタイムでしゃべった言葉を認識するような形式を取れば サクサク動くのかもしれません。 何やら複雑なことをやってそれを成し遂げている海外の方がいらっしゃいました。(料金ヤバそう) 【参考リンク】:Streaming recognition 【参考リンク】:[Announce] Google Cloud Streaming Speech Recognition [VR\AR\Desktop]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#)】DeepL Translatorの使い方

はじめに UnityからDeepL Translatorを使用する方法をメモします。 DeepL Translator DeepLの提供する翻訳WebAPIです。 下記リンクより登録に進みAPIキーを取得します。 【参考リンク】:DeepL Pro 登録後、下記ダッシュボードの画面からAPIキーを取得可能です。 料金は従量課金制ですが、1月当り500,000文字までは無料で使えるようです。(GoogleTranslationと一緒でした) バージョン 念のため使ったライブラリ等のバージョンも書いときます。 Unity 2019.4.8f1 UniTask.2.2.4 UniRx 7.1.0 コード Unityから使用するサンプルです。 GIFにおいては使用しているAPIは異なりますが、下記と同様に動作します。 【参考リンク】:【Unity(C#)】Microsoft Translatorの使い方 適当なオブジェクトにアタッチ using System; using System.Linq; using System.Threading; using Cysharp.Threading.Tasks; using UniRx; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; /// <summary> /// DeepLの最小構成サンプル /// </summary> public class DeepLTest : MonoBehaviour { [SerializeField] private Dropdown fromLanguageDd; [SerializeField] private Dropdown toLanguageDd; [SerializeField] private Button translateButton; [SerializeField] private InputField inputField; [SerializeField] private Text translationText; private const string API_KEY = "APIキー"; private const string ENDPOINT = "https://api-free.deepl.com/v2/translate?"; /// <summary> /// レスポンスを格納する構造体 /// </summary> [Serializable] public struct TranslateData { public Translations[] translations; [Serializable] public struct Translations { public string detected_source_language; public string text; } } private void Start() { var token = this.GetCancellationTokenOnDestroy(); //ドロップダウンメニュー作成 var languages = Enum.GetNames(typeof(Language)); fromLanguageDd.ClearOptions(); fromLanguageDd.AddOptions(languages.ToList()); toLanguageDd.ClearOptions(); toLanguageDd.AddOptions(languages.ToList()); fromLanguageDd.value = (int) fromLanguage; toLanguageDd.value = (int) toLanguage; //翻訳元言語 fromLanguageDd.OnValueChangedAsObservable() .Subscribe(value => { fromLanguage = (Language) value; }) .AddTo(this); //翻訳後言語 toLanguageDd.OnValueChangedAsObservable() .Subscribe(value => { toLanguage = (Language) value; }) .AddTo(this); //翻訳ボタン押下 translateButton.OnClickAsObservable() .Subscribe(async _ => { //結果が送られてくるまで待ってから表示 var result = GetTranslation(fromLanguage, toLanguage, inputField.text, token); translationText.text = await result; }) .AddTo(this); } /// <summary> /// 設定言語 /// </summary> private enum Language { JA, EN } private Language fromLanguage = Language.EN; private Language toLanguage = Language.JA; /// <summary> /// 翻訳結果を返す /// </summary> /// <param name="from">翻訳前の言語設定</param> /// <param name="to">翻訳語の言語設定</param> /// <param name="speechText">翻訳したい文字列</param> /// <param name="ct">CancellationToken</param> /// <returns>翻訳結果</returns> private async UniTask<string> GetTranslation(Language from, Language to, string speechText, CancellationToken ct) { //POSTメソッドのリクエストを作成 var requestInfo = ENDPOINT + API_KEY; requestInfo += $"&text={speechText}&source_lang={from}&target_lang={to}"; var request = UnityWebRequest.Post(requestInfo, "Post"); //結果受け取り var second = TimeSpan.FromSeconds(3); var result = await request.SendWebRequest().ToUniTask(cancellationToken: ct).Timeout(second); var json = result.downloadHandler.text; Debug.Log(json); var data = JsonUtility.FromJson<TranslateData>(json); return data.translations[0].text; } } リクエストパラーメーターとして渡す言語情報の文字列は下記に載っています。 【参考リンク】:Translating text おわりに いろいろな翻訳API使ってみての感想ですが、GoogleもMSも申し分なく精度が高いですが、DeepLはやっぱり一番精度が高いなと感じました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#)】Google Cloud Translationの使い方

はじめに UnityからGoogle Cloud Translationを使用する方法をメモします。 Google Cloud Translation Googleの提供する翻訳WebAPIです。 下記リンクより登録に進みAPIキーを取得します。 【参考リンク】:Translation 登録後、下記ダッシュボードの画面からAPIキーを取得可能です。 料金は従量課金制ですが、1月当り500,000文字までは無料で使えるようです。 バージョン 念のため使ったライブラリ等のバージョンも書いときます。 Unity 2019.4.8f1 UniTask.2.2.4 UniRx 7.1.0 コード Unityから使用するサンプルです。 GIFにおいては使用しているAPIは異なりますが、下記と同様に動作します。 【参考リンク】:【Unity(C#)】Microsoft Translatorの使い方 適当なオブジェクトにアタッチ using System; using System.Linq; using System.Threading; using Cysharp.Threading.Tasks; using UniRx; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; /// <summary> /// GoogleTranslationの最小構成サンプル /// </summary> public class GoogleTranslationTest : MonoBehaviour { [SerializeField] private Dropdown fromLanguageDd; [SerializeField] private Dropdown toLanguageDd; [SerializeField] private Button translateButton; [SerializeField] private InputField inputField; [SerializeField] private Text translationText; private const string API_KEY = "APIキー"; private const string ENDPOINT = "https://translation.googleapis.com/language/translate/v2?"; /// <summary> /// レスポンスを格納する構造体 /// </summary> [Serializable] public struct TranslateData { public Data data; [Serializable] public struct Data { public Translations[] translations; [Serializable] public struct Translations { public string translatedText; public string detectedSourceLanguage; } } } private void Start() { var token = this.GetCancellationTokenOnDestroy(); //ドロップダウンメニュー作成 var languages = Enum.GetNames(typeof(Language)); fromLanguageDd.ClearOptions(); fromLanguageDd.AddOptions(languages.ToList()); toLanguageDd.ClearOptions(); toLanguageDd.AddOptions(languages.ToList()); fromLanguageDd.value = (int) fromLanguage; toLanguageDd.value = (int) toLanguage; //翻訳元言語 fromLanguageDd.OnValueChangedAsObservable() .Subscribe(value => { fromLanguage = (Language) value; }) .AddTo(this); //翻訳後言語 toLanguageDd.OnValueChangedAsObservable() .Subscribe(value => { toLanguage = (Language) value; }) .AddTo(this); //翻訳ボタン押下 translateButton.OnClickAsObservable() .Subscribe(async _ => { //結果が送られてくるまで待ってから表示 var result = GetTranslation(fromLanguage, toLanguage, inputField.text, token); translationText.text = await result; }) .AddTo(this); } /// <summary> /// 設定言語 /// </summary> private enum Language { ja, en } private Language fromLanguage = Language.en; private Language toLanguage = Language.ja; /// <summary> /// 翻訳結果を返す /// </summary> /// <param name="from">翻訳前の言語設定</param> /// <param name="to">翻訳語の言語設定</param> /// <param name="speechText">翻訳したい文字列</param> /// <param name="ct">CancellationToken</param> /// <returns>翻訳結果</returns> private async UniTask<string> GetTranslation(Language from, Language to, string speechText, CancellationToken ct) { //POSTメソッドのリクエストを作成 var requestInfo = ENDPOINT; requestInfo += $"key={API_KEY}&q={speechText}&detectedSourceLanguage={from}&target={to}"; var request = UnityWebRequest.Post(requestInfo, "Post"); //結果受け取り var second = TimeSpan.FromSeconds(3); var result = await request.SendWebRequest().ToUniTask(cancellationToken: ct).Timeout(second); var json = result.downloadHandler.text; Debug.Log(json); var jsonData = JsonUtility.FromJson<TranslateData>(json); return jsonData.data.translations[0].translatedText; } } リクエストパラーメーターとして渡す言語情報の文字列は下記に載っています。 【参考リンク】:言語サポート おわりに DeepLも試したのでまとめます。 試しました→【Unity(C#)】DeepL Translatorの使い方
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む