ArialフォントのTextコンポーネントを洗い出すエディタ拡張【Unity】
概要
WebGLで、デフォルトフォントのArialを使うと日本語が出ない問題がある
Arialを使っているTextコンポーネントの洗い出しがめんどくさい
特に開発終盤になりオブジェクトが増えてきた時。
洗い出しをするエディタ拡張を作る。
動作確認したUnityバージョン
version 2018.2.0f2
使い方
後述のソースコードを、「Assets/Editor」フォルダに入れる。「Editor」フォルダがない場合はフォルダを作成する。
メニュー上部の「Tools/Arialフォント洗い出し」をクリック
ソース
FinderTextHavingArialFont.cs
using System.Linq; using UnityEditor; using UnityEngine; using UnityEngine.UI; namespace CoffeeR{ /// <summary> /// Arialフォントを洗い出すエディタ拡張クラス /// </summary> public class FinderTextHavingArialFont{ [MenuItem("Tools/Arialフォント洗い出し")] static void Exec (){ // シーン中にある、テキストコンポーネント全て取得 var textComponents = UnityEngine.Resources.FindObjectsOfTypeAll( typeof( Text ) ) as Text[]; // Arialな奴の取得 var textsWithArial = textComponents .Where(obj => obj.font.name == "Arial"); // 該当しなければダイアログを出して終了 if(textsWithArial.Count() == 0){ FinderTextHavingArialFont.DrawDialog("問題なし","編集中シーンでフォントがArialのTextはありませんでした。"); return; } // 該当するものがあれば、パスを記録していく。 var explain = "編集中シーンでフォントがArialのTextが見つかりました。"; foreach(var text in textsWithArial){ explain += "\n" + GetHierarchyPath(text.gameObject.transform); } // 該当するオブジェクトのパスをダイアログに表示 FinderTextHavingArialFont.DrawDialog("問題あり", explain); return; } static void DrawDialog(string title, string text){ EditorUtility.DisplayDialog( title, text, "OK" ); } static string GetHierarchyPath(Transform self){ string path = self.gameObject.name; Transform parent = self.parent; while (parent != null){ path = parent.name + "/" + path; parent = parent.parent; } return path; } } }
備考
- コンポーネント初期値の設定はPreset使えば良い
- Unity1週間ゲームジャム向けに作りました。開発終盤なんかのチェックに使うのが良いかと思います。
System.Void Zenject.InjectAttribute::.ctor()' that does not exist・・・みたいなエラーが出てWebGLビルドに失敗した話【Unity Zenject】
1週間ゲームジャム参加の心得メモ
概要
【RT希望】Unity 1週間ゲームジャム 次回は 09/03(Mon) 開催 | 無料ゲーム投稿サイト #unityroom https://t.co/2uhr9rdqDr #unity1week
— naichi (@naichilab) 2018年8月10日
三ヶ月ぶりの開催です〜
ハードル低めのオンラインゲームジャムなので気軽に参加ください〜!一人でもチームでもOKです!
リンク先から過去作品も遊べます!
1週間ゲームジャムの開催が近づいてきた。 開発中迷わないようにするため、これまで参加してきた時に得られた気づきを備忘録としてまとめておく。
参加する上での目標設定
- 順位でTOP6入りを目指す
- 新しい表現方法を習得する
- これまで作ったことのないジャンルの設計を習得する
- 特殊なゲームギミックを実験(面白いか、面白くないのか)
- とにかく完成させて友達や他開発者とわいわい
どのように&どんなゲームを作るかが変わってくる。
「いろんな人に見てもらえる機会」を使って実現できるものを設定すると良さみ。
自分の場合大抵、TOP6入り&友達とわいわいするのを目標。
企画は初日に決める
企画決めました!寝ます。 #unity1week pic.twitter.com/wx4aUBleop
— ☕りょう (@plus_marumaru) June 3, 2018
初日に決めておくと、残りの6日間を実装に回せる。
頭の中にあるイメージをラクガキで残しておく。
テキストだけだとイメージするのが難しい。
土曜に企画立てて作った利用規約ゲームもあるが、全然作り込めなかった。
unityroom利用規約 | ゲーム投稿サイト unityroom #unity1week https://t.co/40hzaTx6Sz
— naichi (@naichilab) 2017年7月30日
利用規約がゲームになるなんて・・・w
土曜日にはプレイ可能なBuildを1つ用意する
日曜日は予備日と思っておく。 だいたい遅延するのでやっぱり日曜日使っちゃうけど。
作る内容に優先順位をつける
みたいなリストを作っておく。時間的に厳しい場面がどうしても出てくるから。
作らない勇気、大事。
機能追加かバランス調整か迷ったらバランス調整を優先する
新しいルールや機能は、ミステリー小説の登場人物を1人増やすようなもの。
開発後半で悩んだらバランス調整優先。
終わった後にブログを書く
事故った経験を忘れないようにしておく。 ライブラリ使おうとしたら〇〇でハマった、とか。 他の人の役に立ったり、1年後の自分が同じことでハマった時に役立つ。
積極的に告知しておく
Unityroom外からの流入を作る。主にTwitter。 頑張って作ったけど、プレイしてもらえたいのは結構悲しいから。 TOP6入りしている人はTwitterで話題になっているのが多い印象。
進捗報告用に動画編集できるようにしておく
Twitterで告知する際はスクショだけだとゲームの面白さが伝わらない。 ので、gifや動画を投稿することを推奨。
他開発者のモチベーションをあげる
面白そうだなと思ったゲームには、Twitter上でいいねをつけておく。
Twitterのいいねは、ゲームジャムにおいて大変良いモチベーションになる。
なんかハマっている時は、自分ができる範囲で協力する。
通信対戦のデバッグとか結構しんどい。
新しい技術はあまり入れない(人によりけり)
入れすぎるとゲーム開発の進捗が上がらない。
こだわらない部分を決める
- UIのボタン→デフォルトのままで良い
- 設計→神クラスになっても良い
- 音楽→自作したい気持ちを抑えて素材サイト様のものを使わせていただく
夢のない話かもしれないが、やらない勇気が完成を導く。
少ないプレイ時間で満足できるようにする
200作品近く投稿される。
プレイ時間が長いとクリア前に他ゲームに遷移してしまう。
操作内容を理解させる
ゲームのファーストビューで見せたり、1プレイ目で操作を説明するとか。
操作がわからなくて離脱してしまうことがしばしばある。
後、開発者ではない身近な友人にプレイしてもらうと良い。
プレイ中の視線の動きやコントローラー/キーボード/マウスの動かし方を見ていれば、理解できているかどうかがわかる。
※開発者はゲームプレイがうますぎるので、難しい操作でも難なくプレイできてしまう。
必要なライブラリは事前にプロジェクトに入れておく
どうせやる作業は事前にやっておく。 自分の場合はUniRx,Zenject,DoTween, Fungus, TextMeshPro
よく使う素材サイトのurlをメモっておく
上記に同じ。ライセンスに気をつける。
あまり注目されないから問題ないだろう。。。とか思っていると、ツイッターでバズった時に死ぬ。
週半ばでWebGLビルドして動作確認する
WebGLのバグ対策。実はこのアセット死んでるとかある。
UnityRoomさんのゲームジャム説明ページをよく見ておく
Unityのバージョンについての注意事項とか書いてある。
後、開発する上でのお役立ち情報とかキャンペーン情報が掲載されていることも。
クソゲーだった時作り直すかどうかの判断
結構難しい問題だと思う。
- 変えずに完成させる→モチベーションがしんどい。
- 切り替えて完成させる→スケジュールがしんどい。
自分の場合は開始2日目まで内容の大幅変更を許容。
それ以降は作りこみが間に合わなそうなのでクソゲーだったとしても作りきる。
実は他の人が遊んだら新しい遊び方が発見されて神ゲーになる可能性もある。
クソゲーを受け入れられる人間になる
半年後にリベンジとして、より面白いものを作れば良い。焦らない!
(社会人)有給を1ヶ月前に申請しておく
残業は作業時間だけでなく開発モチベーションを削る。
社会人&マジでやる人は社内の根回しから行わなければならない。
スーパーアーマーの実装メモ【Unity】
仕様
- 対象はキャラクター
- オブジェクト衝突時にダメージを受ける
- 一度ダメージを受けるとしばらくスーパーアーマー状態
- スーパーアーマー中はダメージを受けない
- 時間の経過でスーパーアーマーは解除される
- スーパーアーマー中キャラを点滅
Unityバージョン
2018.1.0f2 Personal ※UniRx使う
クラス図
- ReactivePropertyを使って、スーパーアーマーである時間を設定
- ダメージを与えるコンポーネントで、スーパーアーマー残り時間が0よりも大きければ攻撃しない
- スーパーアーマー中は、rendererコンポーネントのenableの値を1フレーム置きに更新する
ダメージ処理のフローチャート
コード
IStatus ステータスのinterface ※ここinterfaceにしておけば、ダメージ処理が簡潔に書けると思ってる
using UniRx; public interface IStatus{ ReactiveProperty<float> TimeSuperArmor{get; set;} }
PlayerStatus ステータスの実装 キャラクターオブジェクトにアタッチする
using UnityEngine; using UniRx; public class PlayerStatus : MonoBehaviour , IStatus{ public ReactiveProperty<float> TimeSuperArmor{get; set;} void Awake (){ TimeSuperArmor = new ReactiveProperty<float>(); } }
SuperArmorTimeUpdater 経過時間をinputとして、スーパーアーマーの残り時間を減らしていく キャラクターオブジェクトにアタッチする
using UnityEngine; using UniRx; using UniRx.Triggers; public class SuperArmorTimeUpdater : MonoBehaviour { IStatus status; void Start () { status = this.GetComponent<IStatus>(); this.UpdateAsObservable() .Where(x => status.TimeSuperArmor.Value > 0) .Subscribe(x => { status.TimeSuperArmor.Value -= Time.deltaTime; }); } }
SuperArmorBlinker スーパーアーマー中にレンダラー(キャラクター画像に当たる)を点滅させる キャラクターオブジェクトにアタッチする
using UnityEngine; using UniRx; using UniRx.Triggers; public class SuperArmorBlinker : MonoBehaviour { IStatus status; SpriteRenderer renderer; void Start () { status = this.GetComponent<IStatus>(); renderer = this.GetComponent<SpriteRenderer>(); this.UpdateAsObservable() .Where(x => status.TimeSuperArmor.Value > 0) .Subscribe(x => { renderer.enabled = this.BoolSwitch(renderer.enabled); }); // スーパーアーマーが終わったら、レンダラーを必ず有効にしてあげる status.TimeSuperArmor .Where(time => time <= 0) .Subscribe(time => { renderer.enabled = true; }); } bool BoolSwitch(bool flg){ if(flg == true){ return false; }else{ return true; } } }
Damager ダメージを与えるコンポーネント なんらかの攻撃を行うオブジェクトにアタッチする
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Damager : MonoBehaviour { void OnTriggerEnter2D(Collider2D collider) { // ステータスコンポーネントを取得 var status = collider.gameObject.GetComponent<IStatus>(); // コンポーネントがなければ、ダメージを与えられないオブジェクトとして処理終わり if(status == null){ Debug.Log("ステータスコンポーネントを持っていないオブジェクトと衝突"); return; } // スーパーアーマー中であればダメージを与えない if(status.TimeSuperArmor.Value > 0){ Debug.Log("スーパーアーマー中"); return; } // ここにダメージ処理記述 Debug.Log("ダメージを与えた!!"); // スーパーアーマー状態にする(動作確認用に2.0fにしてます) status.TimeSuperArmor.Value = 2.0f; } }
完成したもの
未検証事項
- rendererのenableを切り替えて点滅させるのではなく、シェーダーを使って点滅させた方が実行速度でる?
TextのColorを変更しても反映されず黒になる問題の解消【Unity】
気づいたらなぜか色変えができなかったので解決方法を備忘しておく。
https://forum.unity.com/threads/ui-text-all-black.407597/
事象が発生したUnityのバージョン
2018.1.0f2 Personal
修正方法
TextコンポーネントのMaterialにFont Materialを入れる
【Unity備忘録】クラス図設計して個人的によかった点
前提
- 設計よくわかってない人間、コーダーとかスクリプターとか
- PlantUMLでクラス図書く
- ZenjectとUniRx使ってみる
- 開発で使える期間は1年間と決まっている
- 個人ゲーム開発
良かった点
予定を立てられる
- エターなりたくない、ならば、いつ開発終わるの?の自問自答に対して答えられるようにしたい
- クラス数最低〇〇個みたいなのが見えてくる
- 技術的に難しそうな箇所の早期発見、早い段階で検証すれば精神的不安も解消
- 「コーディングだけで最低半年かかる」とか分かれば早期に仕様の削り落としとかにも繋がる
重複コードの発見
- 似たようなメンバ変数の構成のコンポーネントが出てくる
- ボタンクリック時とかの処理とか、よく見るとメソッドの引数が違うだけとか
- 共通化しても問題なさそうなところはしていく、コード行数少なければ開発後半の苦しみが減る
- 行き当たりばったりで開発していると気づきにくいかも
自分が書いたコードがわからなくなる現象の回避
- 1個のクラスの役割「do」は1つ〜2つ程度でおさまっているか?
- たくさんあるとシンドイ。プレイヤーの移動&ダッシュ&スーパーアーマー&死亡とかあるとスパゲッティー化
- 役割が複数あるのは分割する
- 逆に役割が0のやつとかがあったりする、そういうのは設計段階でなくす
- クラス図を残しておくと、なんでこれ作ったか思い出すヒントになる
悩みどころ
個人開発でどこまで設計する?
- 事前に設計したとしても仕様の変更とかが出てきてしまう。今の所見た目やアニメーションに関わる部分は変更が激しそうなためあまり設計してない。
- クラス図以外では必要なのか?
【Unity】ゲームのちょっとした会話場面にFungusを使ってみる
アクションゲームでボスキャラとの戦闘前に会話を挟みたい
- ゲームの操作を一時中断させることで休憩してもらい疲れないようにする
- 強敵がくるという危機感や期待感を持ってもらう
という狙いで、会話シーンを作りたい。
会話シーンを作る手段としては考えたのは、
自前スクリプト組む
ノベルゲームを作るためのAssetを使用する
Twitterで見かけたFungusというAssetのが良さそうだったのでこちらを使って見る。 ノベルゲーム開発で大活躍しそう。使い方備忘のため書き残しておく。 このAsset、無料です。
教えてもらった会話アセットFungusが有能すぎる…必要な機能がほぼある。 pic.twitter.com/cK92htfKet
— しめなわん (@shimenawa33) 2018年7月4日
まずは会話ダイアログを出してみる
使っているUnityのバージョン
2018.1.0f2 Personal
AssetをInportする
Flowchartコンポーネントがアタッチされたオブジェクトを作成
メニューのToolsにFungusの項目が追加されているので、こちらから作成。
ヒエラルキーにきのこのマークが付いているオブジェクトが作られます。
FlowchartのWindowを確認
きのこマークが付いているオブジェクトのインスペクターをみて、「Open Flowchart Window」をクリック。
こんな画面が出ることを確認。あとで使います。
SayDialogコンポーネントがアタッチされたオブジェクトを生成
メニューのTools>Fungusから、SayDialogをCreate。
Gameビューを見てみると、会話ダイアログが作られます。
会話テキストを打ち込む
FlowchartのWindowで、「New Block」をクリックして選択。選択すると枠が緑色になる。
インスペクターの「+」マークを押して、Narrative>Sayをクリック。
「Commands」という項目に「Say」の項目が追加されます。
「Say」の部分をクリックして、「Story Text」に会話内容を入力。
ここまでで、▶︎実行をすると会話ダイアログに会話内容が表示されます。
キャラクターを表示させて会話させる
Characterコンポーネントがアタッチされたオブジェクトを生成
メニューのTools>Fungusから、Characterを2つCreate。
作成されたオブジェクトのコンポーネント上で、
- キャラクター名→Name Text
- 関連する会話ダイアログ→Set Say Dialog
- キャラクターの画像→Portraits
を設定。
Stageコンポーネントがアタッチされたオブジェクトを生成
メニューのTools>Fungusから、Stageを2つCreate。Stageコンポーネントでは、キャラクターのデフォルトの位置を設定できるようです。1体のCharacterに対して1つのStageをつくるのがいいのかな?(あんまりわかってない)
Stageコンポーネントが取り付けられてある子オブジェクトに、デフォルトの位置と関連しているオブジェクトがあります。
今回はキャラクターが左右から入ってくるようにしたいと思ったので、「Defalut Position」に「Offscreen ●●」のオブジェクトを指定。
Flowchart Windowでキャラクターを出して会話させる
FlowchartのWindowで、「New Block」 をクリック、Narrative>Portraitを作成して、
- Portrait Stage→先ほど作成したStageを指定
- Display→Showのまま
- Character→作成したCharacterを指定
- Portrait→Characterコンポーネントの「Portraits」で指定した画像を選択
- Move→チェックボックスをつける
- From Position, To Position→キャラクターの移動開始位置、終了位置を指定
- Wait Until Finished→アニメーションが完了したら次のCommandを行うか、すぐさま次のCommandを行うかのフラグ?
この状態で▶︎実行すると、左右からキャラクターが画面中央に移動しながら表示されます。
あとはNarrative>Sayしてどのキャラクターに会話させるか指定させテキストを打ち込み、 Narrative>Portraitして会話終了タイミングでキャラクターを左右にフェードアウトさせることでそれっぽくなります。 できたのがこちら。
会話処理を発火させる
FlowchartのWindowで、発火させる条件が指定できます。
または、スクリプトからFlowchartコンポーネントのExecuteBlockメソッドを使えば任意の場所で発火させることができました。
会話終了タイミングで処理を呼び出す
インスペクターの「+」で、Scripting>Invoke Eventでコマンド追加すれば、ButtonコンポーネントのOnClickのように実行するメソッドを指定できる。 これ以外でもできそうです。
その他
繰り返しますが無料です。すごい。