クリスマス・・去年倒したはずなのに 。
日本の欝ソングって言えばこの『クゥリスマスが今年もやあてくルゥー』とサザエさんのEDだと思われるのですが。
サザエさんのエンディングは会社をやめて何年も経つのに、聞くたびにモリモリと力が抜ける魔性のソングだし。
くぅーりすます の方は言わずもがな世の中のリア充をのろってしまうそんな定番ソングであるわけです。
あと5月5日にフルーツバスケットのOPなんかが流れてくるのも ちょっぴり悲しく欝になる そんな感じ。
それと 仕事の締切が迫ると必ず見る夢があって、それは大学で1教科単位を落として進級できないという夢。
いつか忘れるんじゃないかと思っていたんだけど 最近いきつけの歯医者にはなしをしたら『ぶぎょうさんも
見るんだー 僕もね未だにテストが白紙で進級できない夢見るんだよ すごいプレッシャーなんだろうねw』
てな話をされた。歯医者はもうすぐ70才 えー また欝になったよ・・・
忘れた頃にはじめる スクリプト話
『Unity3D+AI』で検索をかける方がおおいようなので 少し話をしてみます
一般的にゲームに使用されるのは 移動、攻撃、回避 などの思考ルーチンをセットにしたもの
移動は ランダムな移動 と 定点への移動(パトロール) があります。
■ランダム移動
transform.position = Random.insideUnitSphere * 5.0;
を使用します。球面のランダムなポイントを返してくる関数で、半径を掛けて使用しましょう。この場合は5.0が半径です。
2次元座標に使用する場合は transform.position.z = 0;などを実行して球の高さ方向の値を
0としてしてしまえば良いと思います。
単に2次元で方向をもとめるだけならば Random.insideUnitCircle を使用して
var position : Vector2 = Random.insideUnitCircle * 5;
と半径5の円上のポジションをもとめるやり方もあります。
また 地面上のあるポイントを算出したい場合 キャラクターコントローラーがあれば地面上をあるかせることは非常に簡単になるので
function Update () {
var hit : RaycastHit;
if (Physics.Raycast (transform.position, -Vector3.up, hit)) {
var PointOnGround = hit.point;
}
}
などとして ポジション値を返してやることで、地形上のランダム移動は可能だと思います。
レイキャストでどのような値が帰ってくるかは RaycastHit型のリファレンスを見てください。
■ウェイポイント法
レベルマップ上にウェイポイント=決まったポジションを定義してそれらをつなぐライン上を移動させる方法です。
UnityAnswer(Unityの質問掲示板)に簡単なウェイポイントのスクリプトがあったので解説しますね。
var waypoint : Transform[];
/// 型宣言に[]をつけてで配列型を宣言します ///
static var speed : float = 5;
private var currentWaypoint : int;
private var TurningSpeed : float = 15;
function Update ()
{
if(currentWaypoint < waypoint.length)
//// 〇〇.length で配列の大きさが帰ってきます ////
{
var target : Vector3 = waypoint[currentWaypoint].position;
///Vector3型 (x,y,z)の形のベクトルデータを指定 ///
var moveDirection : Vector3 = target - transform.position;
/// モデルの動く方向 ///
var velocity = rigidbody.velocity;
if(moveDirection.magnitude < 1)
/// Vector3.magnitudeで距離を計算 ///
{
currentWaypoint++;
/// ウェイポイントまでの距離が1以下ならば現在のウェイポイントのナンバーをひとつ進める
(距離が1より小さい場合は計算から除外する)///
}
else
{
velocity = moveDirection.normalized*speed;
///方向を正規化したもの(方向だけだとベクトルに大きさがあるため)に
スピード値をかけてvelocity(速度)を計算する///
}
}
rigidbody.velocity = velocity;
/// verocity(速度)でrigidbody.velocity(このスクリプトをつけたモデルの速度値を更新///
/////////////////////////////////////////////////////
var lookAt = waypoint[currentWaypoint].position - transform.position;
lookAt.y = 0;
var rotation = Quaternion.LookRotation(lookAt);//target.position - transform.position
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime *TurningSpeed);
/////////////////////////// 一定時間でQuaternion.Slerp()を使用;モデルをウェイポイントの方向に向かせる ////
}
var lookAt = waypoint[currentWaypoint].position - transform.position;
lookAt.y = 0;
var rotation = Quaternion.LookRotation(lookAt);//target.position - transform.position
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime *TurningSpeed);
この行は
transform.LookAt(waypoint[currentWaypoint].position);
transform.Rotate(transform.rotation.x, 0, transform.rotation.z);
こう書いてもいいです。
このスクリプトは基本平面を自由に動きまわるタイプFPSなどを想定しているようです。
コレ以外にも例えばレースゲームなども似た感じのスクリプトで動作できます例えば コース上に最速ラインのポイントをいくつか設定し配列に格納して順番に読み出しアザーカーがそれを目指すように実行します。
このときウェイポイントはゲーム中の最速タイムをだしたラインをレコードして使用するなどとすれば学習の効果が現れます。
自分の関わったゲームだとレコードされたラインを複数持ちランダムにポイントを選択していました。
このほかにグリッドを使用して最短経路をもとめるA*(エースター)などの方法があるので
調べてみてください。
関連して移動のための判断材料として点数を付ける方法があります。
新しく移動する位置の候補を選び出して、その場所について 敵に攻撃が通るか、立ち状態で攻撃できるか、座り状態で攻撃可能か、
相手からの攻撃エリアにはいっていないか などにそれぞれ点数をつけて得点の高い場所を有効として移動目標にする方法です。
将棋などの思考ルーチンもこうした計算がベースになっているようですので 応用範囲は広い気がします。
■攻撃について
相手が見える位置にいる→攻撃できる→距離が有効→角度が有効(視野角に入っている)などの簡単なチェックを
行います。
/////////////////////////////////////距離を求めます
var target : Transform;
if (other) {
var dist = Vector3.Distance(target.position, transform.position);
if (dist < 100.0)
実行文・・・・
}
/////////////////////////////////////敵の方向と自分の向いている方向との角度を求めます
var targetDir = target.position - transform.position;
var forward = transform.forward;
var angle = Vector3.Angle(targetDir, forward);
if (angle < 5.0)
実行文・・・・
}
のように 距離と角度を求めて攻撃の判定を出すかどうかを決定します。
敵との距離に応じて使用武器を変化するなどとすればさらにプレイに緩急がつくでしょう。
ちなみに距離は
var sqrLen = (other.position - transform.position).sqrMagnitude;
でももとめることが出来ます。数式で書くと√(x*x+y*y+z*z) になる わけですが Vector3.magnitude を使うより実行が速いと
リファレンスに書いてあるんですがこれほんとなのかな?
そしておおまかに ファジー関数を用いてこれらの決定に重み付けをしたりニューラルネットで学習を施すなどの味付けをするなどと
すればより賢いスクリプトが仕上がってくるはず?
特に決まりはないのでじぶんの思いついたやり方でそれっぽくなれば、おっけーというぐらいで
あまりやりすぎてもゲーム自体が重くなってしまうので注意したほうがいいでしょうね。
相手に攻撃が通るかは 前述したレイを飛ばす方法でコリジョンヒットしたら攻撃は通らないということです。
ウェイポイントによる移動はFPSのチュートリアルの人間型敵の移動を、
ランダムな移動はUnityのTPSのチュートリアルの空をとぶボール型の敵を参考にすればいいかと思います。
あとロコモーションシステムについてくる自由移動のスクリプトも見ておきましょう。
詳しい説明は もう少し勉強が進んだら時間のあるときにやります。 たぶんw
ちょっと閑話休題
わたしがメーカ内にいたときに見た思考プログラムはif分の塊で 高度なものを期待している人はちょっと肩透かしな気になるかもしれません。
理由は幾つかあって
○グループで製作されるため誰でも見通しのよい読みやすいものにすること。
○引継ぎしやすさも考えて並易に書くこと。
○動けば良い。
などの理由があったようです。
洗練されたスクリプトを書くと自分自身があとで理解不能になったりしますよねw なので自分の書きたいように書いてかまわない
けど表現の簡単なものをと教えられました。
あと 『コピペ推奨』と『書いたものは消さない』というのも教えられましたね。
同じ物をかくのにコピペを禁止したりすることがあるようですけど 時間がかかる上にバグのもとになりやすいです。
一度書いたものはコメントラインで残しておくと再編集が容易になるし思考の流れが記録されます。
はー長くなってしまった 今後の予定として ブログの方はきちんと講座形式でやりたいんですが(私のつたない知識では物足りないと思いますけど) ストパンstgの方も計画が遅れまくっているので気長にやっていきますよ ええ。 春まで仕事が山積していて予定通りにはいかないと思いますが
あてにしないで待っていてください いや そのうちUnityのいい本がでるはず みんなそれを買ってw。
追記: すっごく中途半端な記事になってしまったので、おすすめリンクを載っけときます。
http://www-cs-students.stanford.edu/~amitp/gameprog.html
日本の欝ソングって言えばこの『クゥリスマスが今年もやあてくルゥー』とサザエさんのEDだと思われるのですが。
サザエさんのエンディングは会社をやめて何年も経つのに、聞くたびにモリモリと力が抜ける魔性のソングだし。
くぅーりすます の方は言わずもがな世の中のリア充をのろってしまうそんな定番ソングであるわけです。
あと5月5日にフルーツバスケットのOPなんかが流れてくるのも ちょっぴり悲しく欝になる そんな感じ。
それと 仕事の締切が迫ると必ず見る夢があって、それは大学で1教科単位を落として進級できないという夢。
いつか忘れるんじゃないかと思っていたんだけど 最近いきつけの歯医者にはなしをしたら『ぶぎょうさんも
見るんだー 僕もね未だにテストが白紙で進級できない夢見るんだよ すごいプレッシャーなんだろうねw』
てな話をされた。歯医者はもうすぐ70才 えー また欝になったよ・・・
忘れた頃にはじめる スクリプト話
『Unity3D+AI』で検索をかける方がおおいようなので 少し話をしてみます
一般的にゲームに使用されるのは 移動、攻撃、回避 などの思考ルーチンをセットにしたもの
移動は ランダムな移動 と 定点への移動(パトロール) があります。
■ランダム移動
transform.position = Random.insideUnitSphere * 5.0;
を使用します。球面のランダムなポイントを返してくる関数で、半径を掛けて使用しましょう。この場合は5.0が半径です。
2次元座標に使用する場合は transform.position.z = 0;などを実行して球の高さ方向の値を
0としてしてしまえば良いと思います。
単に2次元で方向をもとめるだけならば Random.insideUnitCircle を使用して
var position : Vector2 = Random.insideUnitCircle * 5;
と半径5の円上のポジションをもとめるやり方もあります。
また 地面上のあるポイントを算出したい場合 キャラクターコントローラーがあれば地面上をあるかせることは非常に簡単になるので
function Update () {
var hit : RaycastHit;
if (Physics.Raycast (transform.position, -Vector3.up, hit)) {
var PointOnGround = hit.point;
}
}
などとして ポジション値を返してやることで、地形上のランダム移動は可能だと思います。
レイキャストでどのような値が帰ってくるかは RaycastHit型のリファレンスを見てください。
■ウェイポイント法
レベルマップ上にウェイポイント=決まったポジションを定義してそれらをつなぐライン上を移動させる方法です。
UnityAnswer(Unityの質問掲示板)に簡単なウェイポイントのスクリプトがあったので解説しますね。
var waypoint : Transform[];
/// 型宣言に[]をつけてで配列型を宣言します ///
static var speed : float = 5;
private var currentWaypoint : int;
private var TurningSpeed : float = 15;
function Update ()
{
if(currentWaypoint < waypoint.length)
//// 〇〇.length で配列の大きさが帰ってきます ////
{
var target : Vector3 = waypoint[currentWaypoint].position;
///Vector3型 (x,y,z)の形のベクトルデータを指定 ///
var moveDirection : Vector3 = target - transform.position;
/// モデルの動く方向 ///
var velocity = rigidbody.velocity;
if(moveDirection.magnitude < 1)
/// Vector3.magnitudeで距離を計算 ///
{
currentWaypoint++;
/// ウェイポイントまでの距離が1以下ならば現在のウェイポイントのナンバーをひとつ進める
(距離が1より小さい場合は計算から除外する)///
}
else
{
velocity = moveDirection.normalized*speed;
///方向を正規化したもの(方向だけだとベクトルに大きさがあるため)に
スピード値をかけてvelocity(速度)を計算する///
}
}
rigidbody.velocity = velocity;
/// verocity(速度)でrigidbody.velocity(このスクリプトをつけたモデルの速度値を更新///
/////////////////////////////////////////////////////
var lookAt = waypoint[currentWaypoint].position - transform.position;
lookAt.y = 0;
var rotation = Quaternion.LookRotation(lookAt);//target.position - transform.position
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime *TurningSpeed);
/////////////////////////// 一定時間でQuaternion.Slerp()を使用;モデルをウェイポイントの方向に向かせる ////
}
var lookAt = waypoint[currentWaypoint].position - transform.position;
lookAt.y = 0;
var rotation = Quaternion.LookRotation(lookAt);//target.position - transform.position
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime *TurningSpeed);
この行は
transform.LookAt(waypoint[currentWaypoint].position);
transform.Rotate(transform.rotation.x, 0, transform.rotation.z);
こう書いてもいいです。
このスクリプトは基本平面を自由に動きまわるタイプFPSなどを想定しているようです。
コレ以外にも例えばレースゲームなども似た感じのスクリプトで動作できます例えば コース上に最速ラインのポイントをいくつか設定し配列に格納して順番に読み出しアザーカーがそれを目指すように実行します。
このときウェイポイントはゲーム中の最速タイムをだしたラインをレコードして使用するなどとすれば学習の効果が現れます。
自分の関わったゲームだとレコードされたラインを複数持ちランダムにポイントを選択していました。
このほかにグリッドを使用して最短経路をもとめるA*(エースター)などの方法があるので
調べてみてください。
関連して移動のための判断材料として点数を付ける方法があります。
新しく移動する位置の候補を選び出して、その場所について 敵に攻撃が通るか、立ち状態で攻撃できるか、座り状態で攻撃可能か、
相手からの攻撃エリアにはいっていないか などにそれぞれ点数をつけて得点の高い場所を有効として移動目標にする方法です。
将棋などの思考ルーチンもこうした計算がベースになっているようですので 応用範囲は広い気がします。
■攻撃について
相手が見える位置にいる→攻撃できる→距離が有効→角度が有効(視野角に入っている)などの簡単なチェックを
行います。
/////////////////////////////////////距離を求めます
var target : Transform;
if (other) {
var dist = Vector3.Distance(target.position, transform.position);
if (dist < 100.0)
実行文・・・・
}
/////////////////////////////////////敵の方向と自分の向いている方向との角度を求めます
var targetDir = target.position - transform.position;
var forward = transform.forward;
var angle = Vector3.Angle(targetDir, forward);
if (angle < 5.0)
実行文・・・・
}
のように 距離と角度を求めて攻撃の判定を出すかどうかを決定します。
敵との距離に応じて使用武器を変化するなどとすればさらにプレイに緩急がつくでしょう。
ちなみに距離は
var sqrLen = (other.position - transform.position).sqrMagnitude;
でももとめることが出来ます。数式で書くと√(x*x+y*y+z*z) になる わけですが Vector3.magnitude を使うより実行が速いと
リファレンスに書いてあるんですがこれほんとなのかな?
そしておおまかに ファジー関数を用いてこれらの決定に重み付けをしたりニューラルネットで学習を施すなどの味付けをするなどと
すればより賢いスクリプトが仕上がってくるはず?
特に決まりはないのでじぶんの思いついたやり方でそれっぽくなれば、おっけーというぐらいで
あまりやりすぎてもゲーム自体が重くなってしまうので注意したほうがいいでしょうね。
相手に攻撃が通るかは 前述したレイを飛ばす方法でコリジョンヒットしたら攻撃は通らないということです。
ウェイポイントによる移動はFPSのチュートリアルの人間型敵の移動を、
ランダムな移動はUnityのTPSのチュートリアルの空をとぶボール型の敵を参考にすればいいかと思います。
あとロコモーションシステムについてくる自由移動のスクリプトも見ておきましょう。
詳しい説明は もう少し勉強が進んだら時間のあるときにやります。 たぶんw
ちょっと閑話休題
わたしがメーカ内にいたときに見た思考プログラムはif分の塊で 高度なものを期待している人はちょっと肩透かしな気になるかもしれません。
理由は幾つかあって
○グループで製作されるため誰でも見通しのよい読みやすいものにすること。
○引継ぎしやすさも考えて並易に書くこと。
○動けば良い。
などの理由があったようです。
洗練されたスクリプトを書くと自分自身があとで理解不能になったりしますよねw なので自分の書きたいように書いてかまわない
けど表現の簡単なものをと教えられました。
あと 『コピペ推奨』と『書いたものは消さない』というのも教えられましたね。
同じ物をかくのにコピペを禁止したりすることがあるようですけど 時間がかかる上にバグのもとになりやすいです。
一度書いたものはコメントラインで残しておくと再編集が容易になるし思考の流れが記録されます。
はー長くなってしまった 今後の予定として ブログの方はきちんと講座形式でやりたいんですが(私のつたない知識では物足りないと思いますけど) ストパンstgの方も計画が遅れまくっているので気長にやっていきますよ ええ。 春まで仕事が山積していて予定通りにはいかないと思いますが
あてにしないで待っていてください いや そのうちUnityのいい本がでるはず みんなそれを買ってw。
追記: すっごく中途半端な記事になってしまったので、おすすめリンクを載っけときます。
http://www-cs-students.stanford.edu/~amitp/gameprog.html