Ctrlもしくは左クリックで射撃、マウスで標準合わせ(画面中央)、十字キーで移動です。
今作っているFPS風ゲームが出来上がりつつあります。
Photonを使って、ネットワーク上での撃ち合いができたら良いと思って作っています。
取り急ぎ、簡単な撃ち合いが出来るようになったので、上記ボタンから、遊んで頂けたらとても嬉しいです。
少なくとも2人いないと撃ち合いになりませんのでゲームが成立しません。お誘いあわせの上お楽しみください。
参考にしたのは下記の動画です。FPSゲームを作成するUnity公式のチュートリアルです。
ゲーム制作した上で工夫した点をいくつか、かいつまんで記録しておきます。
まず、photonとStandardAssetという無料のアセットをインポートしました。
photonについては以下の記事をご参照ください。 もしよろしければ、Photonについて私が知りえる限りの情報を徹底的にまとめてみたので、下記の記事も読んで下さいね!
FPS の動きをするスクリプトや本体はStandard Asset にもともと入っているものを使用したので、特別な事は何もしないでプレイヤーは十字キーで動かすことが出来ました。
Photonで使用するので、Resource folderにプレファブ化して格納しました。
もちろんPhoton view.csをアタッチして以前ポーカーの手札でやったように、お互いにネットワーク上で見えるようにします。
お互いの位置の同期はポーカーの手札と同じ要領で、同期を取っています。
スクリプトとしては下記のコールーチンの内容ともう一つの塊がデータのやり取りをやってそうだと思います。
コールーチンはStartCoroutine("UpdateData");で呼び出しています。
IEnumerator UpdateData() { while (true) { transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * smoothing); transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * smoothing); yield return null; } } void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { if (stream.isWriting) { stream.SendNext(transform.position); stream.SendNext(transform.rotation); stream.SendNext(health); } else { position = (Vector3)stream.ReceiveNext(); rotation = (Quaternion)stream.ReceiveNext(); health = (float)stream.ReceiveNext(); } }
細かい事は抜きにして、コピペで動きました。
何故動くかはチュートリアルで詳しい解説があります。
元のチュートリアルのソースコードは下記に公開されているので、ここでお話ししている事の全体を確認する上で下記のコードを見ていただくと、何の話をしているのかより分かりやすくなります。
Merry Fragmas: Multiplayer FPS, Part 2
FPSplayerのInstantiateについては4つのキューブの位置にランダムで出現するようになっています。
これは、もともとのスクリプトの仕様がそうなっているためです。
キューブの配列を母集団に取るようになっているので、キューブを全選択して、インスペクター上にドラッグ&ドロップしてあります。
上の公開されているソースではアニメーションの処理など色々入っています。
私が作成したゲームの方は、かなり単純化されていて、アニメーションの処理は全部削ってあります。
使い方が分からなかったせいです。勉強が進み次第アップデートするかもしれません。
FPSplayerが出来た状態で、ネットワーク上で二つのキャラを動かそうとすると、両方が動いてしまいます。これはもちろん、同じソースがくっついているので当たり前です。
これを防ぐためにFPSplayerのPrefabのチェックボックスを全部オフにします。
そして、photonView.isMineがtrueの時のみ、スクリプトによってオンにしてあげます。要するに、自分のコントロールするプレファブのみ、インスペクター上のコンポーネントがオンになるようにします。
if (photonView.isMine) { //rigidbody.useGravity = true; GetComponent<FirstPersonController>().enabled = true; GetComponent<CharacterController>().enabled = true; GetComponent<AudioSource>().enabled = true; GetComponentInChildren<GunShooting>().enabled = true; //foreach (SimpleMouseRotator rot in GetComponentsInChildren<SimpleMouseRotator>()) // rot.enabled = true; foreach (Camera cam in GetComponentsInChildren<Camera>()) cam.enabled = true; }
ここら辺のソースコードはそのチェックボックスをオンにしている所です。
下記図のように、インスペクター上ではphotonViewとPlayerNetworkMover以外は全部オフにしています。
次に、苦労したのはGunShootingのスクリプトです。
ほぼ、コピペですが、FPSplayerの抱えているシリンダーの正面に対してRayを発射しています。
ところが、その正面とは真下方向だったのですね。これには、デキる人に指摘してもらうまで気づきませんでした。
シリンダーそのものではなくparentのカプセルの正面になるようにコードを改変しています。
if (Physics.Raycast(transform.position, transform.parent.forward, out hit, 50f))
あとは、エフェクトをつけたり、音を入れたり、しました。
苦労したのはリプレイボタンを再表示させるというところです。SetActiveを使う際に一度falseにしてしまうと、もう一度trueにしても、効かないのですね。
それを防ぐためには親子関係の親から探してあげる必要があります。
GameObject.Find("Canvas").transform.Find("Panel").transform.Find("Button").gameObject.SetActive(true);
SetActiveでfalseした物を再度trueする
詳しくは上記リンクに解説されています。
それから、弾を食らった際には、コールーチンを使って一定時間自分の画面の色が変わるようにパネルを表示させるようにしてあります。
IEnumerator startPush() { if (photonView.isMine) { GameObject.Find("Panel").GetComponent<UnityEngine.UI.Image>().enabled = true; yield return new WaitForSeconds(0.5f); GameObject.Find("Panel").GetComponent<UnityEngine.UI.Image>().enabled = false; } }
工夫したのはそれくらいでしょうか。
今後の課題としては相手のライフが見える化できると良いなと思っています。カプセルの色がより不健康な色に変わっていく等の処理を入れたいと思っています。
先ほどもこのリンクを貼りましたが、Photonについて私が知りえる限りの情報を徹底的にまとめてみたので、Photonに興味が出てきたら、下記の記事も読んで下さいね!
Merry Christmas!!!