チュートリアル前回のチュートリアルでは、ゴルフっぽいゲームで使うコースを作成しました。Prefabからオブジェクトをインスタンス化し、手動で配置するのって結構楽しい気がします。今回は、前回作成しなかったゴールを設置するのと、ボタンの動きを少し変えてゲーム全体の進行を制御するようにしてみます。前回のチュートリアルはこちらから。pocket【第25回】ゴルフっぽいゲームのコースを作るUnityチュートリアルhttps://ekulabo.com/tutorial-create-course単純な斜方投射を拡張し、ゴルフのようなゲームを作るチュートリアルです。今回はコースを作成しています。Prefab化したオブジェクトを配置していくのはよくある方法なので、息をするようにオブジェクトを配置できるように慣れていくといい感じ。まとめ今回の目的コースのゴールを配置し、スタートからゴールまでの全体の進行を制御します。ゴールに到達したら、UIテキストをアニメーションさせます。前回のチュートリアルで作成したプロジェクトをそのまま使います。このページに先にたどり着いた方は、チュートリアルの初回から追っていただけるといいかもしれません。IDも登録してサインインした。いうあなたに向けた超入門チュートリアルです。Unityの物理演算を体験するため、物体を自由落下させてみましょ。何をもってゲームのゴールとするか、というのはどんなゲームでも考えないといけないことですね。このゲームはゴルフっぽいゲームを目指しているので、ボールが到達するゴールを作成しないといけません。分かりやすいのはゴール用オブジェクトを作ってしまうことなので、サクッとやっちゃいましょ。テクスチャは以下のものを使います。右クリックで保存してください。ゴール用テクスチャこのテクスチャをUnityの『Project』ウィンドウ内、『Textures』フォルダにインポートします。エクスプローラ(Win)またはFinder(Mac)からドラッグ&ドロップ。素材をインポートするのだポッターインポート設定は特にいじらなくて大丈夫です。インポートできた続いてマテリアルを作成します。『Materials』フォルダに移動して、右クリックまたは二本指タップでコンテキストメニューを開きます。[Material]を選択。マテリアルの作成Materialの名前は[Goal]にしました。『Goal』マテリアルを選択し、Albedoの左にある丸ボタンからインポートした『goal』をセットします。インポートしたテクスチャをセット続いてゲームのシーン内にゴール用のオブジェクトを作成します。[Cube]を選択します。作成したオブジェクトは[Goal]と名付けました。この『Goal』オブジェクトを選択し、Transformコンポーネントの歯車アイコンから[Reset]を選択した後、PositionのXを[85]に、Yを[0]、Zを[0]にします。ScaleはXが[5]、Yが[0.2]、Zが[5]としています。0.1m分地面に埋まっていますが、あまり地面から出すと側面の衝突でゴール扱いになるので、これを避けています。Colliderでは物理特性マテリアルの『Bound』をセット。Triggerにチェックを入れないように注意。RendererのMaterialsに『Goal』マテリアルをセットします。Rendererまた、ゴールはコースの一部なので、『CourseObject』オブジェクトの子オブジェクトにします。ドラッグ&ドロップで簡単にできます。CourseObjectの子オブジェクトにするまた、ゴールに乗ったことを検知するため、衝突相手を特定するタグを付けます。Unityのデフォルトのタグで[Finish]があるため、それを設定しましょ。Finishタグここまで設定を行うと、以下のようにゴールが表示されました。ゴールが表示されたこのオブジェクトの上で止まった時に、ステージクリアとなるようにしましょ。ゴール時のUIテキストを作成ゴールしたことが分かるように、UIテキストを使って表示してみます。『Hierarchy』ウィンドウから『Canvas』オブジェクトを選択し、右クリックまたは二本指タップでコンテキストメニューを開きます。[Text]を選択してUIテキストを作成します。作成されたオブジェクトは[GoalText]にリネームしました。Transformコンポーネントでは、Widthを[800]に、Heightを[400]に変更します。大きめにババーンと表示しましょ。GoalTextのRectTransform続いてTextコンポーネントの設定です。Textフィールドには[GOAL!!]を入力しました。ゴールした時に表示されるので、お好きな文字列を入れるといい感じ。Sizeは[192]、Alignmentはどちらも中央に。Colorは[FFFFFFFF](白色)にしました。TextコンポーネントいつものようにOutlineコンポーネントを追加しますが、今回は3つOutlineコンポーネントを追加します。ゴールなので大盤振る舞いです。[Outline]と選択してOutlineコンポーネントを3つアタッチします。各コンポーネントの設定は以下の通り。-12Outlineの三連星テキストオブジェクトの設定が終わると、以下のように表示されます。メインのテキストが中心にある白の部分で、こげ茶、オレンジ、薄いピンクの順にOutlineが表示されています。ここまでやるなら画像にしちゃった方が楽かも。Unityの機能でも多少装飾が可能ですよーという紹介のためにこの形にしてみました。Transformコンポーネント内、PositionのXを[1500]にしておきます。画面に映らなくなるので、ゴールした時にスライドインするようにしてみましょ。今の状態では、ボールを1回打ち上げるとそれっきりになってしまいます。ゴールまで続けて打って行きたいので、以下の方針でスクリプトを編集します。何回も続けてボールを打てるようにするボールを打つ向きを前後にしたい落下した時は、初期位置ではなく最後に打った場所に戻すゴールオブジェクトの上で止まったらコースクリアゴールしたら画面にUIテキストを表示これに沿って編集したのが以下のもの。編集の対象はSphereBooster.csで、スクリプトの全文は『GitHub』にあります。ここでは変更点を中心に解説します。Gist.いやもうメンバ変数がえらいこっちゃ。全部は載せきれないので更新箇所だけ。発射ボタンのオブジェクト、ゴール用UIテキストオブジェクトへの参照を用意。次に、initPositionのフィールドを削除します。いうのは、ボール落下時は最後にボールを打った位置に戻したいためです。距離の測定も最後にボールを打った位置を基準にするので、初期位置であるinitPositionは不要となりました。最後にボールを打った位置については、メンバ変数の下の方でprePositionとして格納しています。ボールの射出角度はMinAngleを0度に、MaxAngleを180度にすることで、前後にボールを打つことが可能になります。MaxAngleが90度のままだと、ゴールを飛び越えてしまったら詰みになっちゃうんですよねぇ。あとはフラグやタグを追加しています。Gist.Start()では、メンバ変数でinitPositionを削除したのに連動して、initPositionをセットしていた行を削除しました。新たに追加したのは、boostButtonのButtonコンポーネントへの参照です。Gist.Update()は変更なしで、FixedUpdate()を更新しました。ゴールしたかどうか、『Sphere』オブジェクトの状態を確認するCheckSphereState()を呼ぶようにしています。こちらは新たに追加したメソッドで、詳細は後述します。ボタンが押されたかどうかの判定後は、元々飛行中フラグでボタンの動作を切り替えていましたが、ここからは発射だけを行うようにします。そのため、ボタンが押された後にcanButtonPressをfalseにし、それをboostButtonのinteractableにセットすることで、ボールの飛行中は発射させないようにしています。canButtonPressはキーボードからの入力を拾うかどうかのフラグにもしています。発射だけになったので、飛行中フラグのisFlyingはtrueのみをセットするようにしました。Gist.StopFlying()では、距離のリセットやガイドの表示などを行なっていましたが、それらの処理をReadyToBoost()にまとめました。ボールを戻す処理については、初期位置initPositionではなく、ボール発射時の位置であるprePositionをセットするようにしています。Gist.BoostSphere()の変更点は、ボールが発射される時の位置を記憶するようにした点のみです。Gist.CheckDistance()ではinitPositionを使って計算していた部分をprePositionに変更しました。Gist.続いて落下判定についてです。ここでは元々、ボタン押されたよフラグをtrueにしていたのですが、ボタンの動作を変えたため明示的にStopFlying()を呼ぶようにしました。Gist.ここは今回のキモ。other)を追加しています。これは衝突したフレーム/衝突から離れたフレームに呼ばれるメソッドです。other)と似ていますね。Trigger』にチェックを入れたかどうかで呼ぶメソッドが変わるんです。Trigger』がfalseならOnCollisionほにゃららを呼びます。引数がCollider型だったりCollision型だったりで紛らわしいことこの上ないですね。ここでやっていることは単純で、『Sphere』オブジェクトの衝突相手がゴールオブジェクトだったらisTouchingGoalのフラグをtrueにし、ゴールオブジェクトから離れたらフラグをfalseにしています。Gist.CheckInput()ではキーボードのBキーが押された時、同時にcanButtonPressフラグも確認するようにしています。canButtonPressは画面に表示している発射ボタンと連動させているので、キーボードからの入力でも同じ動作となるようにしています。Gist.CheckSphereState()はFixedUpdate()から読んでいるメソッドで、ゴールで止まったのか、別の場所で止まったのかを確認しています。ゴールで止まった場合は、ゴールテキストがスライドインするアニメーションを開始させ、hasReachedGoalフラグをtrueにしています。このフラグがtrueの時には処理を行わないので、ゴール処理を1回だけ実施するようにしています。アニメーションの処理を実装したメソッドはStartCoroutineで呼んでいます。コルーチンについてはやっぱりUnityのマニュアルを見るのが一番なのですが、ざっくり言えば時間の経過を伴う処理を実装するための機能です。処理を一定時間停止させるウェイトとか、徐々にオブジェクトを動かしたりだとか。Update()を使ったりして呼ぶと、同じフレーム内で処理を完結させちゃうから、途中を描画してくれないんですよね。そこでコルーチンを使って、ちょっとずつオブジェクトを移動させて、アニメーションしているように表現することができます。ゴール以外では、ボールを発射するための準備を行うようにしています。ReadyToBoost()はこの次に説明します。Gist.ReadyToBoost()は元々StopFlying()の中で行なっていた処理が多く含まれています。ボール落下時と、コース内での停止時では処理が若干異なるため、共通化できる部分をReadyToBoost()として切り出しています。この処理の最後にcanButtonPressをtrueにして、ボタンを押せるようにしています。Gist.コルーチンはIEnumeratorを使って書きます。最初にRectTransformコンポーネントの参照をキャッシュし、whileの中でゴールテキストの位置のセットに使います。initPosでゴールテキストの初期位置を保持し、targerPosでは移動先の位置を保持します。initPosにlocalPositionをセットしているのは、このオブジェクトで設定したPositionを使って欲しいためです。通常のpositionを使ってしまうと、親オブジェクトの位置まで考慮されるためずれてしまいますからね(1敗)finishTimeは処理完了の予定時刻。Time.timeで現在時刻を取得し、引数で渡された秒数を足した時刻にしています。whileの中でこのfinishTimeを見ており、finishTimeを超えていたら、最後にtargetPosをセットして処理終了となります。rateは、引数で渡された秒数に対して、どれだけ時間が経過したかの割合を表しています。Clamp01は0と1の間に値を制限するメソッドで、この後のVector3.Lerpの引数で渡す時に必要になります。Vector3.Lerpは線形補間を行うメソッドで、今回の場合だと、ゴールテキストの初期位置とターゲットの位置を直線で結び、その直線上の位置を割合に応じて返すもの。徐々にオブジェクトを移動させるのにぴったりです。yieldを使った場合、その次のフレームで処理を再開します。ここではnullを返していますが、WaitForSecondsなどを使うと、指定した秒数だけ処理を待つこともできます。コルーチンは、時間を絡めた処理を実装するのに便利です。以下...この辺りの処理はテラシュールブログさんの記事を参考にさせてもらっています。今回の変更点は以上です。スクリプトの全文は『GitHub』にあります。オブジェクト参照の設定スクリプトを変更したら、忘れずにオブジェクト参照をセットします。『Sphere』オブジェクトを選択し、BoostButtonObjectに『Button』オブジェクトをセット。GoalTextObjectには『GoalText』オブジェクトをセットします。動作確認んじゃ確認しましょ。GIFにしてみたら容量がえらいことになったので、YouTubeに上げています。中身についてですが、ボールを一度発射した後、停止した時に再度ボールを発射できるようになっています。発射する向きも後ろまで選べるようになっていますし、ゴールの上で止まったらアニメーションします。あとは細かいところですが、ボールが止まるまでの時間を短くするのと、落下時に少し演出を加えてみましょ。まとめ今回は盛りだくさんで、ゴールの作成とその動作を実装しました。スタートからゴールまでの制御もできるようになったので、細かいところを修正して完成にしましょ。次回はボールが止まるまでの時間を早送りできるようにするのと、落下時の演出を加えます。エクスプラボ【第27回】timeScaleを使ってボールを加速させるUnityチュートリアルhttps://ekulabo.com/tutorial-time-scale単純な斜方投射を拡張し、ゴルフのようなゲームを作るチュートリアルです。Rigidbodyがスリープの状態になることを検知して、次のボールが打てるようにしていましたが、物理演算がスリープに入るまでちょっと時間がかかるんですよね。早送りボタンを実装しまし...ゲーム開発の攻略チャートを作りました!「ゲームを作ってみたいけど、何から手を付けていいか分からない!」そんなお悩みをお持ちの方向けに、todoがアプリをリリースした経験を中心に、ゲーム作りの手順や考慮すべき点をまとめたe-bookを作成しました。ゲーム作りはそれ自体がゲームのように楽しいプロセスなので、「攻略チャート」と名付けています。投稿一覧Unityを使ってアプリを作ったり、Assetを作ったりしてる個人開発者。Unity全般ネタとAsset開発の情報を扱っています。Asset開発は日本語の情報が少ないのよね。ことで些細なネタでも情報を蓄積するのが目的です。2018.05.05単純な斜方投射を拡張し、ゴルフのようなゲームを作るチュートリアル、そのまとめです。2018.04.13斜方投射でボールが飛んだ後、地面を転がって停止した位置までの距離を測定するUnityチュートリアルです。2018.04.10Unityでゲームを作るにあたって、PCならキーボードを使えますが、モバイルでは画面内にUIを用意して操作できるようにします。2018.04.16画面に表示したSliderを使ってカメラをズームイン・ズームアウトさせるUnityチュートリアルです。2018.04.30単純な斜方投射を拡張し、ゴルフのようなゲームを作るチュートリアルです。今回はコースを作成しています。コメントをキャンセルメールアドレスが公開されることはありません。コメントデータの処理方法の詳細はこちらをご覧ください。todoUnityのアセットを作ったり、スマホ向けのアプリを作っています。このブログではUnity初心者に向けたチュートリアルやテクニックを放出しています。詳しいプロフィールはこちら。お仕事の相談や現在提供中のサービスについては、こちらの『サービス内容』のページをご覧ください。Explorers_todoオンライントレーニングのサイトをオープン!エクスプラボを運営しているtodoが、より集中的にゲーム作りについて学べるオンライントレーニングのサイトをオープンしました。エクスプラボのトレーニングルーム』です。勉強したことの進捗も表示できるようになっているので、どれだけ頑張ったのかが分かるようになっています。ゲーム開発の攻略チャート』というe-bookをプレゼントしています。メルマガではゲーム開発のテクニックを中心に役立つ情報をお届けします。詳しくはこちら!お仕事の依頼はこちら!ゲーム開発のサポートも可能!エクスプラボではゲーム開発のサポートのサービスも行なっています。いう場合にオススメのプランです。詳細はこちら!もちろん、普通に開発依頼をいただいてもお手伝いします。その場合はお問い合わせへ。【Unity】ポストプロセシングを使って簡単にプロっぽいゲーム画面を作るゲームの作り方を学べるオンライン講座のサイトをオープンしました!RANKING【Unity】Mathfの切り上げ、切り捨て、偶数丸め。使い分けが大事よねMathf【Unity】ゲームといえばランダム要素。(12)作ったアプリ空とにゃんこと風船と癒し系縦スクロール避けゲーの『空とにゃんこと風船と』(TODOWORKS名義でリリース)気軽に遊べるスマートフォン向けアプリです。ボクセルアートで彩られるどこかレトロ、でも新しい世界で癒されてみませんか?ぼく、猫ですって!タップ系RPG『ぼく、猫ですって!』(TODOWORKS名義でリリース)気軽に遊べるスマホRPG。