tag:crieit.net,2005:https://crieit.net/tags/%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0%E3%82%B2%E3%83%BC%E3%83%A0/feed 「タイピングゲーム」の記事 - Crieit Crieitでタグ「タイピングゲーム」に投稿された最近の記事 2021-03-06T10:10:58+09:00 https://crieit.net/tags/%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0%E3%82%B2%E3%83%BC%E3%83%A0/feed tag:crieit.net,2005:PublicArticle/16720 2021-03-06T10:10:58+09:00 2021-03-06T10:10:58+09:00 https://crieit.net/posts/Unity-6042d6a2eaa82 Unityで複数の入力方法に対応するタイピングゲームを作ろう <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p>はじめまして、情報系の大学に通っているプログラム初心者の大学生です。</p> <p>2年前にゼミ内で小さなゲームジャムが開催され、タイピングゲームを作ることになったのですが、ネット上で紹介されている既存のタイピングゲームの制作方法では入力方法に以下のような問題があると思いました。</p> <blockquote> <p><strong>1. 単語を打つ手段があらかじめ決まっている。</strong><br /> 例 : "し"と打つときに"si"と打たなければいけなく、"shi"には対応していない。</p> <p><strong>2.単語を別々に入力できない。</strong><br /> 例 : "ちゃ"と打つときに"ち"と"ゃ"を別々にタイプできない。</p> </blockquote> <p>そこで今回はどんな打ち方にも対応できるタイピングゲームの制作に挑戦してみました。<br /> この記事では仕組みとプログラムに関して紹介していきます、参考にしていただければ幸いです。</p> <h2 id="参考にした作品"><a href="#%E5%8F%82%E8%80%83%E3%81%AB%E3%81%97%E3%81%9F%E4%BD%9C%E5%93%81">参考にした作品</a></h2> <p>今回制作したプログラムでは「寿司打」のタイピングシステムを参考にしています。</p> <blockquote> <h5 id="寿司打"><a href="#%E5%AF%BF%E5%8F%B8%E6%89%93">寿司打</a></h5> <p><a target="_blank" rel="nofollow noopener" href="http://typingx0.net/sushida/play.html">こちらからプレイできます。</a></p> </blockquote> <p>どのようなシステムかというと</p> <blockquote> <p><a href="https://crieit.now.sh/upload_images/fa30eaea18027ff67c2127f6331493a76041ad3275209.PNG" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fa30eaea18027ff67c2127f6331493a76041ad3275209.PNG?mw=700" alt="キャプチャ1.PNG" /></a><br /> ゲーム画面ではこのようにタイプする文字と入力方法が表示されています。<br /> <strong>この状態で"し"を"si"ではなく"shi"と入力しようとすると...</strong></p> <p><a href="https://crieit.now.sh/upload_images/bebc0f0840b25025f197a22b24571bb26041ae559e71d.PNG" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/bebc0f0840b25025f197a22b24571bb26041ae559e71d.PNG?mw=700" alt="キャプチャ3.PNG" /></a><br /> <strong>"sh"と入力した時点で1つ目の"し"の入力方法が"shi"に置き換わります。</strong><br /> (2つ目の"し"の入力方法は変わらず表示されている。)</p> </blockquote> <p>他にも</p> <blockquote> <p><a href="https://crieit.now.sh/upload_images/2f27d696448dc1a99860914e503c80d76041b0d905c92.PNG" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/2f27d696448dc1a99860914e503c80d76041b0d905c92.PNG?mw=700" alt="キャプチャ4.PNG" /></a><br /> <strong>"ック"を入力する際に、"xtu"と"ku"で別々に入力しようとすると...</strong></p> <p><a href="https://crieit.now.sh/upload_images/f414647101ae6ff6105459a3b582bd3b6041b26740466.PNG" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/f414647101ae6ff6105459a3b582bd3b6041b26740466.PNG?mw=700" alt="キャプチャ5.PNG" /></a><br /> <strong>"xtu"の"x"を入力した時点で”ッ”と"ク"を別々と考えて入力方法を置き換えています。</strong></p> </blockquote> <h2 id="プログラム"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0">プログラム</a></h2> <p>筆者なりに上記のシステムを再現しようとすると以下のようなプログラムになりました。</p> <h3 id="Kanji.txt"><a href="#Kanji.txt">Kanji.txt</a></h3> <blockquote> <p>タイピングゲーム内で使う文章をそのまま入力します。<br /> 一度のタイピングで入力する長さを決めて改行してください。</p> </blockquote> <pre><code>別に君を求めてないけど 横にいられると思いだす。 君のドルチェ&ガッパーナの その香水のせいだよ。 </code></pre> <h3 id="Japanese.txt"><a href="#Japanese.txt">Japanese.txt</a></h3> <blockquote> <p>Kanji.txtの内容を全てひらがなにして入力してください。</p> </blockquote> <pre><code>べつにきみをもとめてないけど よこにいられるとおもいだす。 きみのどるちぇあんどがっぱーなの そのこうすいのせいだよ。 </code></pre> <h3 id="KanjiFuri.txt"><a href="#KanjiFuri.txt">KanjiFuri.txt</a></h3> <blockquote> <p>Kanji.txt内の文字をひらがなにした時、何文字になるかを入力してください(ひらがなの場合は1)</p> </blockquote> <pre><code>21212111111 211111121111 2111113111111 1122111112 </code></pre> <h3 id="Dictionary.cs"><a href="#Dictionary.cs">Dictionary.cs</a></h3> <blockquote> <p>全ての入力方法を連想配列で整理しています。<br /> 下の方にある関数はKeyかValueを渡すことで紐づけられた要素を全て取り出すことができます</p> </blockquote> <pre><code>using System.Collections; using System.Collections.Generic; using UnityEngine; public class Dictionary : MonoBehaviour { //デフォルトの入力方法 public readonly Dictionary<string, string> dic = new Dictionary<string, string>() { {"あ", "a"},{"い", "i"},{"う", "u"},{"え", "e"},{"お", "o"}, {"か", "ka"},{"き", "ki"},{"く", "ku"},{"け", "ke"},{"こ", "ko"}, {"さ", "sa"},{"し", "si"},{"す", "su"},{"せ", "se"},{"そ", "so"}, {"た", "ta"},{"ち", "ti"},{"つ", "tu"},{"て", "te"},{"と", "to"}, {"な", "na"},{"に", "ni"},{"ぬ", "nu"},{"ね", "ne"},{"の", "no"}, {"は", "ha"},{"ひ", "hi"},{"ふ", "hu"},{"へ", "he"},{"ほ", "ho"}, {"ま", "ma"},{"み", "mi"},{"む", "mu"},{"め", "me"},{"も", "mo"}, {"や", "ya"},{"ゆ", "yu"},{"よ", "yo"}, {"ら", "ra"},{"り", "ri"},{"る", "ru"},{"れ", "re"},{"ろ", "ro"}, {"わ", "wa"},{"を", "wo"},{"ん", "n"}, {"が", "ga"},{"ぎ", "gi"},{"ぐ", "gu"},{"げ", "ge"},{"ご", "go"}, {"ざ", "za"},{"じ", "zi"},{"ず", "zu"},{"ぜ", "ze"},{"ぞ", "zo"}, {"だ", "da"},{"ぢ", "di"},{"づ", "du"},{"で", "de"},{"ど", "do"}, {"ば", "ba"},{"び", "bi"},{"ぶ", "bu"},{"べ", "be"},{"ぼ", "bo"}, {"ぱ", "pa"},{"ぴ", "pi"},{"ぷ", "pu"},{"ぺ", "pe"},{"ぽ", "po"}, {"ぁ","xa" },{"ぃ","xi" },{"ぅ","xu" },{"ぇ","xe" },{"ぉ","xo" }, {"っ", "xtu"}, {"ゃ","xya" },{"ゅ","xyu" },{"ょ","xyo"}, {"きゃ","kya"},{"きぃ","kyi"},{"きゅ","kyu"},{"きぇ","kye"},{"きょ","kyo"}, {"しゃ","sya"},{"しぃ","syi"},{"しゅ","syu"},{"しぇ","she"},{"しょ","syo"}, {"ちゃ","tya"},{"ちぃ","tyi"},{"ちゅ","tyu"},{"ちぇ","tye"},{"ちょ","tyo"}, {"にゃ","nya"},{"にぃ","nyi"},{"にゅ","nyu"},{"にぇ","nye"},{"にょ","nyo"}, {"ひゃ","hya"},{"ひぃ","hyi"},{"ひゅ","hyu"},{"ひぇ","hye"},{"ひょ","hyo"}, {"みゃ","mya"},{"みぃ","myi"},{"みゅ","myu"},{"みぇ","mye"},{"みょ","myo"}, {"りゃ","rya"},{"りぃ","ryi"},{"りゅ","ryu"},{"りぇ","rye"},{"りょ","ryo"}, {"ぎゃ","gya"},{"ぎぃ","gyi"},{"ぎゅ","gyu"},{"ぎぇ","gye"},{"ぎょ","gyo"}, {"じゃ","zya"},{"じぃ","zhi"},{"じゅ","zyu"},{"じぇ","zye"},{"じょ","zyo"}, {"ぢゃ","dya"},{"ぢぃ","dyi"},{"ぢゅ","dyu"},{"ぢぇ","dye"},{"ぢょ","dyo"}, {"びゃ","bya"},{"びぃ","byi"},{"びゅ","byu"},{"びぇ","bye"},{"びょ","byo"}, {"てゃ","tha"},{"てぃ","thi"},{"てゅ","thu"},{"てぇ","the"},{"てょ","tho"}, {"うぁ","wha"},{"うぃ","whi"},{"うぇ","whe"},{"うぉ","who"}, {"でゃ","dha"},{"でぃ","dhi"},{"でゅ","dhu"},{"でぇ","dhe"},{"でょ","dho"}, {"くぁ","qa"},{"くぃ","qi"},{"くぇ","qe"},{"くぉ","qo"}, {"ふぁ","fa"},{"ふぃ","fi"},{"ふぇ","fe"},{"ふぉ","fo"}, {"ヴぁ","va"},{"ヴぃ","vi"},{"ヴ","vu"},{"ヴぇ","ve"},{"ヴぉ","vo"}, {"ぴゃ","pya"},{"ぴぃ","pyi"},{"ぴゅ","pyu"},{"ぴぇ","pye"},{"ぴょ","pyo"}, {"、","," },{"。","."},{"「","["},{"」","]"}, }; //デフォルトではない入力方法 public readonly Dictionary<string, string> Epicdic = new Dictionary<string, string>() { {"ca","か" },{"ci","し" },{"cu","く" },{"ce","せ" },{"co","こ" }, {"cha","ちゃ"},{"chi","ち"},{"chu","ちゅ"},{"che","ちぇ"},{"cho","ちょ"}, {"cya","ちゃ"},{"cyi","ちぃ"},{"cyu","ちゅ"},{"cye","ちぇ"},{"cyo","ちょ"}, {"fu","ふ"}, {"ja","じゃ"},{"ji","じ"},{"ju","じゅ"},{"je","じぇ"},{"jo","じょ"}, {"la","ぁ" },{"li","ぃ" },{"lu","ぅ" },{"le","ぇ" },{"lo","ぉ" }, {"lya","ゃ" },{"lyu","ゅ" },{"lyo","ょ" }, {"ltu", "っ"}, {"nn","ん" }, {"qu","く" },{"qyi","くぃ"},{"qye","くぇ"}, {"sha","しゃ" },{"shi","し"},{"shu","しゅ"},{"she","しぇ"},{"sho","しょ"}, {"tsu","つ"}, {"yi","い"},{"ye","え"}, }; //渡した要素と紐づいている要素をdicから探し、リストにして返します。 public KeyValuePair<string, string> SearchdicKey(string key) { var dicpair = new KeyValuePair<string, string>(); foreach (KeyValuePair<string, string> pair in dic) { if (key == pair.Key) { dicpair = pair; } } return dicpair; } //渡した要素と紐づいている要素をdicから探し、リストにして返します。 public KeyValuePair<string, string> SearchdicValue(string value) { var dicpair = new KeyValuePair<string, string>(); foreach (KeyValuePair<string, string> pair in dic) { if (value == pair.Value) { dicpair = pair; } } return dicpair; } //渡した要素と紐づいている要素を両方のdicから探し、リストにして返します。 public List<KeyValuePair<string, string>> SearchTotaldicKey(string key) { var dicpair = new List<KeyValuePair<string, string>>(); foreach (KeyValuePair<string, string> pair in Epicdic) { if (key == pair.Value) { dicpair.Add(new KeyValuePair<string, string>(pair.Value, pair.Key)); } } foreach (KeyValuePair<string, string> pair in dic) { if (key == pair.Key) { dicpair.Add(pair); } } return dicpair; } //渡した要素と紐づいている要素を両方のdicから探し、リストにして返します。 public List<KeyValuePair<string, string>> SearchTotaldicValue(string value) { var dicpair = new List<KeyValuePair<string, string>>(); foreach (KeyValuePair<string, string> pair in Epicdic) { if (value == pair.Value) { dicpair.Add(pair); } } foreach (KeyValuePair<string, string> pair in dic) { if (value == pair.Key) { dicpair.Add(new KeyValuePair<string, string>(pair.Value, pair.Key)); } } return dicpair; } } </code></pre> <h3 id="SetList.cs"><a href="#SetList.cs">SetList.cs</a></h3> <blockquote> <p>次にタイピングするKanjij.txtと同じ行にあるJapanese.txtとKanjiFuri.txtの文字列をSetLists()に渡し、それぞれを区分しながらListに要素を追加していきます。</p> <p>・Japanese.txtは一度に入力可能でありながら、文字列が最長になるように区分し、FuriListに追加していきます。<br /> ・KanjiFuri.txtは1つの数字ごとに文字列を区分しながらKanjiFuriListに追加していきます。<br /> ・また、FuriListに要素を追加しながらDictionary.dicから入力方法を取得し、RomaListに追加していきます。</p> </blockquote> <pre><code>using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class SetList : MonoBehaviour { private SetText ST; private Dictionary Dic; public List<string> RomaList; public List<string> FuriList; public List<int> KanjiFuriList; void Awake() { ST = GetComponent<SetText>(); Dic = GetComponent<Dictionary>(); } private string FuriStr = ""; private string RomaStr = ""; //FuriStrとRomaStrの内容をそれぞれのリストに入れて初期化する。 private void AddList() { FuriList.Add(FuriStr); RomaList.Add(RomaStr); FuriStr = ""; RomaStr = ""; } //渡されたJapanese.txtの一行を一文字づつ仕分けるよう public void SetLists(string Roma , string KanjiFuri) { for(int i = 0; i < Roma.Length - 1; i++) { var chr = Roma[i].ToString(); switch (chr) { case "っ": FuriStr += chr; if (i != Roma.Length - 1) { switch(Roma[i + 1].ToString()) { case "あ": case "い": case "う": case "え": case "お": case "な": case "に": case "ぬ": case "ね": case "の": case "ん": RomaStr += Dic.SearchdicKey(Roma[i + 1].ToString()).Value; AddList(); break; default: RomaStr += Dic.SearchdicKey(Roma[i + 1].ToString()).Value.Substring(0,1); break; } } else { FuriStr += chr; AddList(); } break; case "ぁ": case "ぃ": case "ぅ": case "ぇ": case "ぉ": case "ゃ": case "ゅ": case "ょ": if (i != 0 && FuriStr != "") { if (Dic.dic.ContainsKey(FuriStr + chr)) { FuriStr += chr; RomaStr += Dic.SearchdicKey(Roma[i - 1].ToString() + chr).Value; AddList(); } else { AddList(); FuriStr += chr; RomaStr += Dic.SearchdicKey(chr).Value; AddList(); } } else { FuriStr += chr; RomaStr += Dic.SearchdicKey(chr).Value; AddList(); } break; case "ん": FuriStr += chr; RomaStr += Dic.SearchdicKey(chr).Value; if (i != Roma.Length - 1) { switch(Roma[i + 1].ToString()) { case "あ": case "い": case "う": case "え": case "お": case "な": case "に": case "ぬ": case "ね": case "の": case "ん": case "や": case "ゆ": case "よ": case "ゃ": case "ゅ": case "ょ": RomaStr += "n"; break; } } else { RomaStr += "n"; } AddList(); break; default: if (i != Roma.Length - 1) { switch (Roma[i + 1].ToString()) { case "ぁ": case "ぃ": case "ぅ": case "ぇ": case "ぉ": case "ゃ": case "ゅ": case "ょ": FuriStr += chr; break; default: FuriStr += chr; RomaStr += Dic.SearchdicKey(chr).Value; AddList(); break; } } else { FuriStr += chr; RomaStr += Dic.SearchdicKey(chr).Value; AddList(); } break; } } int num = 0; for(int i = 0; i < KanjiFuri.Length - 1; i++) { num += KanjiFuri[i] - '0'; KanjiFuriList.Add(num); } } } </code></pre> <h3 id="SetText.cs"><a href="#SetText.cs">SetText.cs</a></h3> <blockquote> <p>txtファイルや表示中の文字列の行数、打ち終わった字数などを管理しています。</p> </blockquote> <pre><code>using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class SetText : MonoBehaviour { private SetList SL; private TypingSystem TS; [SerializeField] private TextAsset Furigana = null; //ここにKanjiFuri.txtを入れる [SerializeField] private TextAsset Hiragana = null; //ここにJapanese.txtを入れる [SerializeField] private TextAsset Kanji = null; //ここにKanji.txtを入れる [SerializeField] private List<string> FuriList = new List<string>(); [SerializeField] private List<string> HiraList = new List<string>(); [SerializeField] private List<string> KanjiList = new List<string>(); [SerializeField] private Text RomaText = null; //ここにKanjiFuri.txtの内容を表示するためのテキストを入れる [SerializeField] private Text FuriText = null; //ここにJapanese.txtの内容を表示するためのテキストを入れる [SerializeField] private Text KanjiText = null; //ここにKanji.txtの内容を表示するためのテキストを入れる [SerializeField] private int ColumunNum = -1; //現在打っている文字列の行数、最初に+1するため最初は-1にする private int SetColumunNum { get { return ColumunNum; } set { ColumunNum = value; SL.SetLists(HiraList[ColumunNum],FuriList[ColumunNum]); KanjiProp = 0; ListProp = 0; FuriProp = 0; RomaProp = 0; } } public int Romanum { get; private set; } public int Furinum { get; private set; } public int Kanjinum { get; private set; } public int Listnum { get; private set; } //メインの文字の設定 private int KanjiProp { get { return Kanjinum; } set { Kanjinum = value; var kanjifuristr = "<color=\"red\">"; kanjifuristr += KanjiList[ColumunNum].Insert(Kanjinum, "</color>"); KanjiText.text = kanjifuristr; } } //フリガナの文字の設定 private int FuriProp { get { return Furinum; } set { Furinum = value; var furistr = "<color=\"red\">"; furistr += HiraList[ColumunNum].Insert(Furinum, "</color>"); FuriText.text = furistr; while (Furinum >= SL.KanjiFuriList[Kanjinum]) { KanjiProp++; } } } //SetList.FuriListの何個目の要素を打っているか private int ListProp { get { return Listnum; } set { if(value == SL.FuriList.Count) { ResetText(); return; } else if(value != 0) { FuriProp += SL.FuriList[Listnum].Length; } Listnum = value; } } //ローマ字の設定 public int RomaProp { get { return Romanum; } set { Romanum = value; if (Romanum == SL.RomaList[Listnum].Length) { ListProp++; TS.ResetTypedStr(); RomaProp = 0; } else { var romastr = "<color=\"red\">"; for (int i = 0; i < SL.RomaList.Count; i++) { var str = SL.RomaList[i]; if (i != Listnum) { romastr += str; } else { romastr += str.Insert(Romanum, "</color>"); } } RomaText.text = romastr; } } } private void Start() { SL = GetComponent<SetList>(); TS = GetComponent<TypingSystem>(); SetStrList(Hiragana, HiraList); SetStrList(Furigana, FuriList); SetStrList(Kanji, KanjiList); ResetText(); void SetStrList(TextAsset textAsset, List<string> list) { var array = textAsset.text.Split('\n'); list.AddRange(array); } } //テキストを初期化する private void ResetText() { SL.FuriList.Clear(); SL.RomaList.Clear(); SL.KanjiFuriList.Clear(); SetColumunNum++; } } </code></pre> <h3 id="TypingSystem.cs"><a href="#TypingSystem.cs">TypingSystem.cs</a></h3> <blockquote> <p>txtファイルや表示中の文字列の行数、打ち終わった字数などを管理しています。</p> </blockquote> <pre><code>using System.Collections; using System.Collections.Generic; using UnityEngine; public class TypingSystem : MonoBehaviour { private SetList SL; private SetText ST; private Dictionary Dic; private string Typedstr; public void ResetTypedStr() { Typedstr = ""; } private void Awake() { ST = GetComponent<SetText>(); SL = GetComponent<SetList>(); Dic = GetComponent<Dictionary>(); } string[] keys = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "-", ",",".","[","]"}; //keys内にあるキーを打った時 void Update() { foreach (string key in keys) { if (Input.GetKeyDown(key)) { TypeJudge(key); } } } public void TypeJudge(string type) { //打っている途中の文字と現在打った文字をつなげる var JudgeStr = Typedstr + type; bool jud = false; //打った文字が n で 前の文字が nn じゃない場合 if (type == "n" && SL.RomaList[ST.Listnum] == "n") { SL.RomaList[ST.Listnum] = "nn"; RightEnter(); return; } //正しく打てている場合 if (type == SL.RomaList[ST.Listnum][ST.RomaProp].ToString()) { RightEnter(); } else { //Dictionaryの中のEpicDic内の文字を打とうとしている場合 for (int i = SL.FuriList[ST.Listnum].Length; i != 0 && !jud ; i--) { var SearchStr = SL.FuriList[ST.Listnum].Substring(0,i); if (i != 1 && SL.FuriList[ST.Listnum][0].ToString() == "っ") { SearchStr = SearchStr.Substring(1, SearchStr.Length-1); } var list = Dic.SearchTotaldicKey(SearchStr); foreach (var d in list) { var MatchStr = ""; if (i != 1 && SL.FuriList[ST.Listnum][0].ToString() == "っ") { MatchStr += d.Value.Substring(0, 1); } if (JudgeStr.Length <= MatchStr.Length + d.Value.Length && !jud) { MatchStr += d.Value; if (JudgeStr == MatchStr.Substring(0, JudgeStr.Length)) { //print(MatchStr + "で見つかりました"); TypeMatch(i , MatchStr); } } } } //該当した文字が無い場合(ミスタイプしている場合) if(!jud) { MissEnter(); } } //EpicDic内にある文字が正しく打てている時に呼び出される //打った文字とまだ打っていない文字を切り分ける作業をする void TypeMatch(int num, string MatchStr) { jud = true; var Furistr = SL.FuriList[ST.Listnum]; SL.FuriList[ST.Listnum] = Furistr.Substring(0, num); SL.RomaList[ST.Listnum] = MatchStr; if(Furistr.Length != num) { SL.FuriList.Insert(ST.Listnum + 1, Furistr.Substring(num)); SL.RomaList.Insert(ST.Listnum + 1, Dic.SearchdicKey(SL.FuriList[ST.Listnum + 1]).Value); } Typedstr = JudgeStr; RightEnter(); } //ミスタイプしたとき void MissEnter() { print("ミスしました!"); } //正しく打てているとき void RightEnter() { Typedstr = JudgeStr; ST.Romanum++; } } } </code></pre> <h2 id="実際に動かしてみる"><a href="#%E5%AE%9F%E9%9A%9B%E3%81%AB%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">実際に動かしてみる</a></h2> <p>上にあるプログラムを全て同じオブジェクトにアタッチし、以下の画像のように設定すると動きます。<br /> <a href="https://crieit.now.sh/upload_images/003fafc46d6d8a6b98c5c0b37c69efcc6042d4410d2b1.PNG" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/003fafc46d6d8a6b98c5c0b37c69efcc6042d4410d2b1.PNG?mw=700" alt="キャプチャ.PNG" /></a></p> <h2 id="完成した作品"><a href="#%E5%AE%8C%E6%88%90%E3%81%97%E3%81%9F%E4%BD%9C%E5%93%81">完成した作品</a></h2> <p>そしてこのプログラムを組み込んで実際に完成した作品がこちらになります。</p> <blockquote> <h5 id="ケロツグ -雨乞いタイピング-"><a href="#%E3%82%B1%E3%83%AD%E3%83%84%E3%82%B0+-%E9%9B%A8%E4%B9%9E%E3%81%84%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0-">ケロツグ -雨乞いタイピング-</a></h5> <p><a target="_blank" rel="nofollow noopener" href="https://game.nicovideo.jp/atsumaru/games/gm13342">Webからのプレイはこちらから。</a><br /> <a target="_blank" rel="nofollow noopener" href="https://drive.google.com/drive/folders/1rJD0wXc3cIBas-bnDUSY_-UlANOCqGbo?usp=sharing">プロジェクトのダウンロードはこちらから</a></p> </blockquote> <p>芥川龍之介の「蛙」の文をひたすら打つタイピングゲームです。<br /> 文字を打つたびに蛙が増えていき、正確なタイピングを続けると制限時間が増えたりします。</p> <h2 id="最後に"><a href="#%E6%9C%80%E5%BE%8C%E3%81%AB">最後に</a></h2> <p>作るのは苦戦しましたが内容は結構シンプルな構造になっていると思います。<br /> この方法で作っていると対応していないキーが出てくると思います。<br /> 見つけた場合はDisctionary.csの方に書き足して頂けると対応されると思います。</p> <p>最後まで読んでいただきありがとうございました。</p> かの