Unity敵に追いかけられてみる(3
さてさて、個人的ごたごたがちょっぴり片付いてヤッホーという気持ちであります。私です。
さて、昨日は別件が気が気がなく上の空な状態でぼちぼち書き綴ったので、見直すのが怖い!まじ、
ので、見直しません(開き直り
えーっと、今回は、
たくさんのあざらしをどこから登場させるか?という話ですね。
まず、
『どこに記述するか』
こちらについては、まぁ、カメラでいいやろ。という形で落ち着いた気がします。
(あざらしを増やしたいならば、あざらし以外に・・・ということだけ覚えてもらえれば。。)
で、次ですよ。
どこから出す?(あざらしを
っていうところですわ。
まぁ、カメラの枠辺りからランダムに出せればいいんじゃね?と思っているわけですが、
これがねぇ、むつかしいww
まぁ、ぼちぼちお絵描きしていきますよ。
まず、枠辺りからランダムに出す!ってのを忘れて
・・・忘れた?おけ、じゃぁ、
じゃあね、カメラの枠内のどこかから、あざらしを出すって考えた時に、
その座標(xとy)はどういう風に書けばいいでっしゃろか?(何弁?
答:Randomeを使う(雑
えーっとですね、ランダムな数値を出すみたいな処理はどんなプログラムにもある(気がする
それはUnityでも例外ではなくてですね、
Random.Range(min値、max値)これでね、
minで指定した値と、maxで指定した値の間の数値をランダムで出してくれるんですよ。
だから、x±9と、y±5の範囲内で1か所ポイントをランダムに選択する方法は、
new Vector2(Random.Range(-9.0f,9.0f),Randome.Range(-5.0f,5.0f));
こんな感じで指定でいるわけですよ。(ちょっと違ってたらごめんね。
しかし、しかしですよ。
これがですね、「カメラの枠外から」となると話は変わるわけです。
・・・どうやる?
みたいになりません?
まぁ、4つの数字が出るランダム出して、
それぞれ、上辺底辺右辺左辺を割り当てて、
で、割り当てると片方の座標が決まるわけですよ。
上辺底辺ならy座標が、
右辺左辺ならx座標が。
で、さらにランダムで残りの決まっていない側の座標をで出せばいいんじゃね?
・・・と思っていた時期も私にありました(さっきまで
Normalizeを見つけるまではね!
あとRandom.insideUnitCircleがあればなんてことはないのさ(`・ω・´)b
えーっと、それぞれを説明しますと、
Random.insideUnitCircleはですね、半径1.0の円の中にランダムなポイントを打ち付けるという野郎です。
だから、このRandome.InsideUnitCircleってのは、
x:±1とy:±1かつ、円の外の部分には入らない座標をとってきてくれるわけです。
はえーすごいねぇUnity(とりあえずほめちぎるスタイル。
えーっと
どこに書くか?
(カメラにセットしているスクリプト
座標位置はどうやって決めるか?
(Randome.InsideUnitCircle と Normarize)
じゃぁ、表示する頻度は?
ま、0.2秒単位くらいがいいかな。(不穏
じゃぁ、準備出来たっぽいしやってみましょう。
では、カメラにセットしているスクリプトを開いて、、
欲しい情報としては、
時間(蓄積用
時間(何秒ごとかの明示
かな?
まぁ書いてみましょう。
public class cameraMove : MonoBehaviour
{
GameObject caractorObject;//プレイヤーのオブジェクト
Vector2 playerIti;//プレイヤー位置
Vector2 itiMax; //最大位置
Vector2 itiMin; //最小位置
Vector2 kameraMin; //カメラ移動最小位置
Vector2 kameraMax; //カメラ移動最大位置
float count_time; //時間カウント用
const float putTime = 0.2f; //時間ごと
下に行を追加しました。えー前回あざらしを追加してどれだけ時間が経ったのかを記録する用(count_time)と、
あざらしをどれだけの時間ごとに表示するのかという時間(putTIme)ですね。
で、Start()内部での処理はこう。
void Start()
{
caractorObject = GameObject.Find("testScnd");
playerIti = transform.position;
itiMax.Set(playerIti.x + 5, playerIti.y + 3);
itiMin.Set(playerIti.x - 5,playerIti.y - 3);
kameraMax.Set(5.46f, 5.09f);
kameraMin.Set(-5.46f, -5.09f);
count_time = 0;
}
一番下の一行、count_time=0(初期化処理)の追加をしました。
では、次に時間のカウント処理を書きましょう。
これはまぁ、Update()に書いてもいいかなぁ、ということで、
void Update()
{
count_time += Time.deltaTime;
}
VisualStudioの先を見通す能力に感服であります
ほぼ勝手に入るw
えーっと、これは時間をカウントアップしています。
なんの時間を足しているかというと、前回動作したフレームから経過した時間を足しています。
Update()はフレームごとに動作するので、直前に動いたフレームとの間の時間を記録していくことで時間を計測しているのですね。
じゃぁ、そのcount_timeがどうなったら更新するのか?
式を考えるんですよ。
えーっと
よっこらしょ。
void Update()
{
count_time += Time.deltaTime;
if (count_time > putTime)
{
count_time = 0 ;
}
}
いったんここまで、
えーっと、putTimeが0.2だから、0.2より大きくなったら、要は前回あざらしを表示してから、0.2秒経過したら処理を行うという感じですわ。
で、えーっと?処理が終了したら、また時間を数えないといけないので、
count_timeをリセットしています。
さてさてそろそろですわ。
あざらしを張り付ける処理を記述していきましょう。
まずは位置決めです。
Randomeを、、、っと?
Randomは複数あるけどどっち使う?という話ですね。
まぁ、ちょろっと調べましたが、UnityEngineのでいいみたいなので、そっちにしようかな。
こういう時は明示。こっちを使いますとわかるように記述します。
えいっとな。
void Update()
{
count_time += Time.deltaTime;
if (count_time > putTime)
{
Vector2 iti = Vector2.zero;
for(; iti == Vector2.zero;)
{
iti = (UnityEngine.Random.insideUnitCircle).normalized;
}
iti = iti * 8;
count_time = 0 ;
}
}
へへへ、がっつり書いてしまった(w
えーっと?ifの中身から説明しますかね。
まず、Vector2型のitiというエリアに(0,0)をセットしています。
えーっと、これから使おうとしている処理ですが、円の中にランダムに点を打つという処理なので、ど真ん中(0,0)に点を打たれると、それ以降の処理に影響が出ちゃうので、それを回避したくてこうしています。
で、実際の回避は次の行ですね。
for(; iti == Vector2.zero;)
親の顔より見てるfor文であります。(詳細は端折るわたし
itiの内容が(0,0)の間この中の処理を繰り返します。
繰り返す内容は
iti = (UnityEngine.Random.insideUnitCircle).normalized;
えーっと、カッコの中から見ましょうか。
UnityEngine.Randome.insideUnitCircle
長くなりましたが、先頭の「UnityEngine」は、どこにあるRandomeを使うか記述しているだけなので、割愛。
Randome.insideUnitCircle
こちらは先述しました。
「半径1の範囲内のどこか、ランダムな座標を拾ってくる」処理
であります。
で、次のnormalized
これがですね、先ほどとってきたランダムな座標位置を、中心位置からの角度を変えることなく、中心に位置から1のところまで移動してくれる
という代物です。(ちょっと不安になるわたし
さっきの図を加工するか。。。
どうですかね、左側、適当にとった座標位置をnormalizedすると右の赤点の座標をとってくれるという感じ。
それがどうしたかって?めちゃくちゃ大事だよ!(この後の処理に)
で、この値を次にどうしているのか、
えーっと8倍しております。
式:iti = iti * 8;
・・・唐突にナスカの地上絵を思い出す私。
ナスカの地上絵のかき方(候補)として、
最初に小さな絵をかいて、それを地面に置き、中心に点を打って、その点から、絵の線までの距離を測り、その距離を何十倍にして、中心と絵の線をつないだ直線の先に点を打ち、その点をつないで、書いたのではないかという小話。(説明へたくそすぎて伝わる気がしないw
えーっと要はこうだ!
なんか説明が雑になってまいりましたな。
要は半径1の円周上にある位置を8倍すると、それは半径8の円周上にある位置になる。
(上図のピンクラインのどこかの位置が取れているはず・・・!)
ということです。
・・・はい。(これ以上詳しく解説できないわたし
まぁ、このあたりに表示させりゃいけるんじゃなかろうかと。。。できたらいいなぁ、
さてさて、ようやくあざらしぺったんこの処理です。
こりゃすぐですよ安心してください。
void Update()
{
count_time += Time.deltaTime;
if (count_time > putTime)
{
Vector2 iti = Vector2.zero;
for(; iti == Vector2.zero;)
{
iti = (UnityEngine.Random.insideUnitCircle).normalized;
}
iti = iti * 8;
iti.x += transform.position.x;
iti.y += transform.position.y;
GameObject azrs = (GameObject)Resources.Load("azarasi");
Instantiate(azrs,iti,Quaternion.identity);
count_time = 0 ;
}
}
えんやこーら(意味不明
えーっと、下の方4行くらいかな?
先ほどの場所決めしょり、ちょっと忘れ物がありました。
iti.x += transform.position.x;
iti.y += transform.position.y;
こいつらですね。
えー、、今回、
カメラが動いている=カメラポジションが常に変動しています。
なので、
「カメラのポジション(中心位置)から、半径8の円周上の位置」
を取りたいので、x、yにそれぞれのカメラのポジションx、yを足しております。
で、つぎ、
GameObject azrs = (GameObject)Resources.Load("azarasi");
こいつが前回準備したResourcesフォルダのやつですね。
Resourcesの中から「azarasi」という名前のオブジェクトをazrsというエリアにロードしております。要はコピーですね。
で、(GameObject)は何者かと言いますと、
Loadで取得した情報はObject型なのですが、この記述をすることでGameObject型に変換しているのです。
(型はそろえないと怒られるのよ…)
で、次の行。
Instantiate(azrs,iti,Quaternion.identity);
これが張り付け処理です。
えーっと?
・張り付けるオブジェクト(「azrs」さっきコピーしたやつ
・張り付ける位置(「iti」さっき計算とかしたやつ
・・・・なんだこれ?(「Quaternion.identity」コピペしてきたので無認識
しゃぁねえぇ、調べる。
おぉ、なるほど、「回転させるかどうか」
みたいですね。
今回あざらしさんは無回転なのでQuaternion.identity(親の向きにそろえる
ですが、例えばミサイルとかね、目標に向かって表示されたい場合は回転の内容を記述するのでしょう。(そこまで調べる気のないわたし
おし、たぶんできたので実行してみましょう
(保存!ほぞん!
ぽちー
大量のピンクアザラシゲットだぜ!いぇーい!
棒人間がもう見えませんわw
よし。いい感じですが、
こちらも時間が経つとオブジェクトができすぎて、いずれはPCが固まる運命なので、さっさと止めてくださいw
~余談~
ちょいちょい調べたところ、角度から位置を算出する処理なんかもできるみたいですね。
(角度を指定すると、その角度の先、中心からの距離が1になる位置を取得するみたいなのを見つけた)
さすがにサインコサインを使っておりましたので、今回はやめておきました。
(私が!説明できないから!
へへへ、私の学力がばれるぜ。。w
ということで、大量のあざらしに囲まれるという夢(?)をかなえましたので、次は、、、あざらしをやっつけるような何かを作れればよいかなと思います。
ではでは。
この記事が気に入ったらサポートをしてみませんか?