Unityを使った3Dゲームの作り方(かめくめ)Unityを使った3Dゲームの作り方(かめくめ)ゲーム開発エンジンUnityを使った3Dゲームの制作に参考になる情報を公開しています。0今回はUnityのカメラ内にゲームオブジェクトがある時だけ何らかの処理を実行してみたいと思います。MonoBehaviourクラスで定義されているメソッドを使うだけなので簡単に出来ます。(^^)/今回は簡単なサンプルとしてヒエラルキーにCubeを作成し、そのCubeがカメラの範囲内にある時だけ時間を進めていき、カメラの範囲外に出たら時間の計測をやめるようにしてみます。上のようにカメラの範囲内の時は時間を計測し、範囲外に出たら計測をやめます。注意が必要なのが2点あり、Unityエディター上だとシーンビューでもOnBecameInvisibleやOnBecameVisibleが呼ばれる為、シーンビューを表示した状態の場合はシーンビューを見ているカメラの範囲が使われてしまいます。確認する時はシーンビューを見えないようにして試してください。一つの注意点はカメラから見えている範囲(ゲームビュー)でCubeが見えている時ではなく、カメラの範囲内か範囲外かという点です。上のように赤い四角で囲ったカメラの範囲で判断されます。ゲームビュー上でCubeが見えていなくてもカメラの範囲に入っていれば時間は計測されます。最後にカメラの見えている範囲内にいるかどうかで時間計測をする機能を作ってみましたが、こちらは『だいたいは見えていないから時間を止めるか』程度の性能になります。(^_^;)スポンサーリンクカメラの範囲内にいる時だけ時間を計測するサンプルの作成それではサンプルを作成していきましょう。Object→Cubeを選択しCubeを配置します。Cubeに新しくVisibleTimeCountScriptという名前のスクリプトを作成し取り付けます。true;}}isInsideCameraがカメラの範囲内かどうかを判定するフラグで、elapsedTimeが経過時間、timeCountTextは計測した時間を表示するテキストを設定します。UpdateメソッドではisInsideCameraがtrueの時だけ時間を計測し、その時間をtimeCountTextに表示します。OnBecameInvisibleメソッドはMonoBehaviourクラスで定義されているメソッドでスクリプトが設定されているレンダラーがカメラの範囲外になった時に呼ばれます。OnBecameVisibleはスクリプトが設定されているレンダラーがカメラの範囲内に来た時に呼ばれます。ここで重要なのがOnBecameInvisibleとOnBecameVisibleが記述されたスクリプトが設定されたゲームオブジェクトがレンダラーコンポーネントを持っている必要があります。Rendererを持っているのでOnBecameInvisibleとOnBecameVisibleメソッドが呼ばれます。Body等にスクリプトを取り付けOnBecameInvisibleやOnBecameVisibleを呼び出す必要があります。Cubeにスクリプトを取り付けたら、次は時間を表示するTextを作成します。Size、Alignment、Color等を変更します。これで時間を表示するTextが出来たので、先ほど作ったCubeに取り付けたVisibleTimeCountScriptのインスペクタのtimeCountTextにドラッグ&ドロップして設定します。これで機能が完成しました。カメラに写っているかどうかで時間を計測する先ほど作ったものはカメラの範囲内にCubeがある場合に時間を計測していました。次はカメラに写っているかどうかで時間を計測するかどうかを決める機能を作ってみます。最初に言及した通り完璧なものではありません。VisibleTimeCountScriptをCtrl+Dキーで複製し、スクリプトの名前をVisibleTimeCountScript2とし、クラス名もVisibleTimeCountScript2とします。elapsedTime.ToString("0:00.00");}}}ターゲットとなるゲームオブジェクトはインスペクタで設定するようにします。horizontalOffsetとverticalOffsetはターゲットの位置を調整するオフセット値です。Updateメソッド内ではCamera.main.WorldToViewportPointメソッドを使ってターゲットのゲームオブジェクトにオフセット値を加えてターゲットゲームオブジェクトの位置のカメラのビューポートの位置を求めます。カメラのビューポートは0~1の間の値が得られX軸は0が左、1が右、Y軸は0が下、1が上になります。今回はターゲットのゲームオブジェクトにCubeを指定しますが、Cubeの位置はCubeの真ん中になるのでカメラの見える位置+Cubeの半分の長さ分を足した時にCubeが見えなくなります。実際にはカメラの角度やターゲットゲームオブジェクトの角度があり、そううまく消えてくれるわけでもないのでオフセット値を使って調整します。ターゲットの位置から上下左右の消える位置を求めカメラのビューポートの範囲内であれば時間計測をしています。Cameraゲームオブジェクトを非アクティブにします。スタンダードアセットのFPSController(Assets/StandardAssets/Characters/FirstPersonCharacter/Prefabs/FPSController)をヒエラルキー上にドラッグ&ドロップをして配置します。FPSContollerの子要素のFPSPersonCharacterにVisibleTimeCountScript2を設定します。FPSControllerの移動はキーボードのASDWもしくは十字キーで行い、視点の変更はマウスを動かします。上のような感じになります。細かくポイントを作り制度を上げるCamera.main.WorldToViewportPointメソッドを使ってゲームオブジェクトのビューポート位置を調べカメラに写っているかどうかで判定する事が出来ました。先ほどのやり方だとオフセット値を使って調整というやや面倒なやり方になるのでゲームオブジェクトの子要素にいくつかのポイントを作り、そのポイントのビューポート位置を全て調べカメラ内にいるかどうかを調べるようにしてみます。VisibleTimeCountScript2をCtrl+Dキーで複製し、名前をVisibleTimeCountScript3とします。elapsedTime.ToString();}}}targetPointsに登録されたターゲット位置の一つ一つのビューポート位置を調べています。やっている事はVisibleTimeCountScript2と同じです。今回はCubeではなく人型モデルで試してみます。子要素に空のゲームオブジェクトを使ってターゲットとなる位置を作成します。上の画像では左右の足のボーンの子要素にそれぞれ2点、頭の子要素に1点、上の画像では見えませんが、両手のボーンの子要素に1点ずつターゲットとなる位置を作成しています。足のボーンの子要素では片方の足に2点のポイントがあるので移動させて足の指の辺りと踵の辺りにします。頭の子要素は頭のてっぺん、両手は両手の指先に移動させます。右手のボーンの子要素に作成したターゲット位置は以下のような位置に移動させます。FirstPersonCharacterにVisibleTimeCountScript3を取り付けます(VisibleTimeCountScript2は無効にします)。上のようにEthanのボーンの子要素に作成したターゲット位置を設定します。試しに実行してみると上のようになりました。Ethan子要素のターゲット位置を増やせばより細かく調べられそうです。複数のキャラクターのどれかがカメラ内にいるか判定したい先ほど作成したEthan子要素にターゲット位置を作り調べる方法で精度が上がりました。複数のキャラクターを配置し、どれかのキャラクターのターゲット位置が見えていたら時間を計測したい場合は全てのキャラクターのターゲット位置をリストに設定しておかなければいけません。これでは大変なので、ターゲット位置をボーンの子要素に配置せず、キャラクターを覆うような8つのターゲット位置を作り大まかに計算し、複数のキャラクターを検査するのをやりやすくします。VisibleTimeCountScript3をCtr+Dキーで複製し、VisibleTimeCountScript4とします。elapsedTime.ToString();}}}targetListにはカメラ位置にいるかどうかを調べるキャラクターを複数設定出来るようにします。targetList分の繰り返しを行い、そのキャラクターの子要素のTargetPointsというゲームオブジェクトを取得し、その子要素にあるそのキャラクターのターゲット位置群のビューポート位置を調べています。どれかのキャラクターのターゲット位置がビューポート内にあれば時間計測をします。2重ループになっているので中のfor文を抜けたらisInsideCameraがtrueだったらそのまま外のforeachも抜けるようにしています。Emptyを選択し、名前をTargetPointsとします。Object→Cubeを選択し、インスペクタのTransformのScaleのXYZを0.1にします。EmptyではなくCubeで作成したのはその位置をわかりやすくする為です。Cubeを移動や複製し、キャラクターを覆うような位置に8つのターゲット位置を作成します。上のような感じでキャラクターを覆うように8つのCubeを配置しました。FirstPersonCharacterのVisibleTimeCountScript3を削除し、VisibleTimeCountScript4を取り付けます。Ethanを選択した状態でCtrl+Dキーを押して複製し、少し移動させておきます。FirstPersonCharacterのVisibleTimeCountScript4のtargetListにカメラ内にいるかどうかを調べたいキャラクターを設定します。これで機能が出来たので、試してみます。上のようになりました。この方法だと複数のゲームオブジェクトを調べたい時に楽になるかなと思います。計算量は多いので調べるキャラクターが多くなると処理が遅くなるかもしれません。上の動画だとCubeをそのまま表示していますが、配置し終わったらCubeのそれぞれのインスペクタのTransformコンポーネント以外の物を削除すれば空のゲームオブジェクトと変わりはないのでそうしてください。この方法の問題点はボーンの子要素にターゲット位置があるわけではないので、アニメーションの動きによっては手や足がキャラクターを囲ったターゲット位置の外へ出てしまってカメラに映っても検知されないという点です。終わりにカメラの範囲内かどうかで何らかの処理を実行したい時もあるかな?と思って今回の機能を作成してみました。カメラから見えているゲームオブジェクトだけ判定するようなプロパティ等もありそうな気がしますが、わたくしは見つけられなかったのでとりあえずこうなりました。コメントをキャンセルメールアドレスが公開されることはありません。コメントデータの処理方法の詳細はこちらをご覧ください。サイト内検索が出来ますプロフィール管理人のかめくめちゃんです。(-_-)メールはこちらにお願いします(記事への質問はコメント欄にお願いいたします)。kamekumechan@gmail.comいずれはSIRENやバイオハザードみたいなアクションゲームを作りたいと思っています。ゲームシナリオが書けないので面白いゲームはなかなか作れません・・・・。(^_^;)名前の由来はカメが好きだからです。Д`)シクシク...お知らせ2020/01/01あけましておめでとうございます。(^^)/ユニティちゃんのRPGを作ってみようのPartyStatusスクリプトでpartyMembersのListの型がCharacterStatusとなっていたのでAllyStatusに変更しました。変更したというか、元々AllyStatusに書き換える前のスクリプトを掲載していたので修正しました。ユニティちゃんのRPGを作ってみよう10ーコマンド画面の作成とステータスの表示ーユニティちゃんのRPGでコマンド画面の作成とステータスコマンドを作成し、選択したキャラクターのステータスを表示するようにしていきます。20:00GetPartyStatusメソッドの戻り値もそれに伴って変更しています。2018/08/07コメント欄へのわたくしの返信は停止しております。わたくしに出来る事は既に記事にしてあるので、ブログ右上の検索窓を活用してください。(._.)またブログの最初の方の機能を積み上げていく記事に関しての疑問点は当ブログ記事のスクリプトの説明と寄せられた質問への回答Unityを使った3Dゲームの作り方(かめくめ)の機能積み上げ形式の記事のスクリプトの説明と寄せられた記事の機能についての質問への回答を掲載しています。21:41も参照してみてください。コメントの返信はありませんが、回答は記事に反映されている可能性があります。当ブログはハイスピードプランです。WordPressの編集画面の動作が早くなった。Unityを使った3Dゲームの作り方(かめくめ).。