忍者ブログ
まったくのプログラミング素人の筆者がC++/HSPを使用してSTG(シューティングゲーム)を作っていく過程を書くブログでしたが最近は脱線気味。プログラミング以外にも、ゲーム関連の記事、日々の戯言など。
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

R-TYPEの反射レーザーみたいなのを作りたいと思って実装してみました。
作っている時に3Dなブロック崩しみたいなの作れそうだなーと思ってちょっと作ってみましたが、奥行きの距離感が全く掴めなくて上手くまとめれませんでしたので出来た所まで版です。


WebGLでビルドしてブラウザで動くようにしたものをGitHubにて公開しています↓
https://xxxx-kt-xxxx.github.io/reflect_laser_test/

unitypackageとProjectSettingsのファイルはこちら
Unity2018.2.11f1使用

Zipファイルになっていますので展開したらReflect_test.unitypackageとProjectSettingsフォルダが入っています。
ファイルメニューのAsset→Import Package→Custom Packageを選択しReflect_test.unitypackageを読み込みます。
ProjectSettingsフォルダは作成したプロジェクトにあるProjectSettingsフォルダに上書きします。
左クリックで弾発射、右クリックで壁生成、マウスでプレイヤー移動です。

実装方法書いてみます。
反射レーザーを作る時に大変なのが反射する角度の計算なんですがUnityにはVector3.Reflect(2Dの場合はVector2.Reflect)という便利な関数があって、この関数を使うと簡単に反射角度の計算が出来ます。
Vector3.Reflectを使用するためにはオブジェクトをRigidbodyにて動かす必要があるのでRigidbodyをアタッチしてIs Kinematicのチェックを外しておきます。
3D表示の2Dゲームの場合はConstraintsのFreeze Position(ゲームの向きによってx,y,zを選択)もチェックを入れておかないと反射した時に変な方向に飛んで行ってしまします。

反射するスクリプトはこんな感じ↓
Laser_move.cs


Vector3 Reflect の説明を見てみると・・・
 Vector3 Reflect (Vector3 inDirection, Vector3 inNormal);と書いてあります。

inDirectionは現在の進行ベクトルです
inNormalは法線ベクトル(面に対して垂直方向のベクトル)
Resultが反射ベクトルとなります。

Vector3 refrectVec = Vector3.Reflect(this.lastVelocity, coll.contacts[0].normal);
this.rb.velocity = refrectVec;
の部分で反射ベクトルの計算をしているのですが、たったこれだけで反射ベクトルを求められるのは簡単で良いです。
尚、このスクリプトを実装するに当たって下記のサイト様の記事を大変参考にさせて頂きました。
http://pafu-of-duck.hatenablog.com/entry/2017/09/02/233158


当初、反射ベクトルの計算方法がわからなかったので反射角度を直接指定するやり方で実装していたのですが、この方法だと斜めの壁に対応出来ないんですよね。


Vector3 Reflectを使用するとこんな感じに


動きとしてはVector3 Reflectを使用した方が正しい動きなのですが、ゲームとしてみると角度指定した方法の方が反射レーザーっぽい気もしますね。
この辺は実際のゲームに合わせて実装するのが良さそうなので、今のところはコレで良しとしておきます。

PR
一番下に追記あります。
**********************************************

先日作成したトレイルレンダラーでレーザーを表示するプログラムを改良してベジェ曲線を使った3次元的なホーミングレーザーを実装してみました。



WebGLでビルドしてブラウザで動くようにしたものをGitHubにて公開しています↓
https://xxxx-kt-xxxx.github.io/Homming_TEST/

unitypackageとProjectSettingsのファイルはこちら
Unity2018.2.11f1使用
Zipファイルになっていますので展開したらHomming_TEST.unitypackageとProjectSettingsフォルダが入っています。
ファイルメニューのAsset→Import Package→Custom Packageを選択してHomming.unitypackageを読み込みます。
ProjectSettingsフォルダは作成したプロジェクトにあるProjectSettingsフォルダに上書きします。
実行すると左クリックした位置に座標(0,0,0)からホーミングレーザーを発射します。
右クリックしながらドラッグするとカメラアングルが変更出来ます。


先日作成したトレイルレンダラーでレーザーを表示するプログラムからの変更点を書いてみます。
まずベジェ曲線を使った3次元的なホーミングレーザーを実装についてですが、以前2次元なホーミングレーザーについては
http://ktstg.blog.shinobi.jp/Entry/658/
http://ktstg.blog.shinobi.jp/Entry/676/
辺りに詳しく書いていますので参考にして下さい。



上の動画のプログラムは↓でダウンロード出来ます。
ベジェ曲線プログラムのダウンロード
ソースファイルと実行ファイルが入ってます。

動画のP03の位置にレーザーを表示すればホーミングっぽく表示出来ますが3次元で表示する場合はどうするんやろ?と悩みみました。
色々ググってみたりしたのですが良くわからず、とりあえず全ての座標でZ軸を追加して計算してみたら上手くいったので今回はコレで良しとしています。

Laser_move.csを下記のように書き換えます。

Laser_move.cs

全ての座標でZ軸の計算を追加しています。座標(0,0,0)からクリックされた位置にレーザーを発射してクリックした位置に来たらトレイルレンダラーを付けた子オブジェクトを切り離してレーザーを消去しています。

今回はクリックした位置にレーザーを移動させますのでLaser_Create.csも下記のように変更します。

Laser_Create.cs


Laser_Tail.csについては14行目を下記のように変更します。
if(time>240)

この状態で再生させるとクリックした場所にホーミングが飛んでくると思うのですが、軌跡が綺麗じゃない(トレイルレンダラーが崩れてしまう)時があるんですよね。

画像のような感じで綺麗に描画されない時があります。
どうやら曲がる角度が急になったりすると崩れてしまうようで、マテリアル変えたりトレイルレンダラーの数値を変えたりしたのですが根本的な解決は自分には出来ませんでした。
一応、トレイルレンダラーの幅を狭くすると目立たなくなるので、とりあえずはこの方法で妥協しようかなぁと思いってます。

トレイルレンダラーの数値Widthを0.1に変更してグラフを画像のように変更します。


マテリアルの画像を↓に変更します。



この状態で再生させるとこんな感じ。

トレイルレンダラーの崩れがかなり軽減されています。もうちょっと太くしたいなーと思いつつ綺麗に見える限界がこの辺かなぁと。
他の対策法としては急な角度がつかないようにするのが良いと思うのですが、良い実装方法が思いつきませんでした。

それと、右クリックしてカメラアングルを動かせるようにするスクリプトはコチラ
CameraRotator.cs

このスクリプトをメインカメラにアタッチすれば右クリックでカメラアングルを変更出来るようになります。
このスクリプトは下記サイトさまのを、そのまま使わせて頂きました。
Unity:マウスドラッグでカメラを回転して視点を操作するスクリプト

*******************************************************************
追記
トレイルレンダラーが崩れてしまう問題ですが、マテリアルの画像を太いものに変更すると上手く出来ました。
laser_tailの画像を下の画像に変更してみて下さい。

お好みで下の画像でも良いです。

ファイル名はlaser_tailに変更して使用して下さい。

この画像でマテリアル作って表示すると、綺麗に表示されるようになりました。

私は勝手に勘違いしていて、画像は小さく(細く)すれば良いと思っていたのですが、画像は大きく(太く)作っておいてトレイルレンダラー側の設定で太さを調整するのが正解のようです。
マテリアルのShaderの設定もAlpha BlendedよりもAdditiveの方が良い感じな気がします。
レーザーを表示したいなと思って実装方法を色々と考えたのですが、Unityにはトレイルレンダラーというオブジェクトが動いた跡の軌跡を表示する機能があったので、それを使って実装してみました。


unitypackageとProjectSettingsのファイルはこちら
ファイルのダウンロード
Unity2018.2.11f1使用
Zipファイルになっていますので展開したらLaser_TEST.unitypackageとProjectSettingsフォルダが入っています。
ファイルメニューのAsset→Import Package→Custom Packageを選択してLaser_TEST.unitypackageを読み込みます。
ProjectSettingsフォルダは作成したプロジェクトにあるProjectSettingsフォルダに上書きします。
実行すると左クリックした位置にレーザーを表示します。

作成方法書いてみます。
まず下の2枚の画像をプロジェクトフォルダの適当な場所に保存します。


ProjectタブのCreateからMaterialをクリックして適当な名前を付けます。Laser_tailとしておきました。


作成したMaterialを選択しInspectorのShaderをParticles→Alpha Blendedに変更します。
画像を選択するSelectを押して、最初に追加した画像Laser_tailに変更します。


同じようにLaser_topのMaterialも作っておきます。

次にHierarchyタブでCreate→3D Object→Planeでオブジェクトを作成します。
名前はLaser_prefabにしておきます。


作成したLaser_prefabを選択してInspectorのMesh RendererのMaterialsのElement 0タブのマテリアルをLaser_topに変更します。
InspectorのScaleをxyz共に0.1にしておきます。


ProjectタブでCreate→Folderで空のフォルダを作成。名前はScriptにします。
ScriptフォルダでCreate→C# Scriptで新しいスクリプトを作成。名前はLaser_moveにして下記のコードを追加します。
Laser_move.cs
 
作成したLaser_moveスクリプトをHierarchyタブにあるLaser_prefabにアタッチします。

HierarchyタブのMainCameraのPositionをXを0、Yを20、Zを-10にします。

この時点で再生ボタンを押してみて弾が移動すればOK。

トレイルレンダラーの設定をします。
HierarchyタブにあるLaser_prefabを選択してInspectorタブのAdd Componentを押してEffect→Trail Rendererを選択します。


Trail RendererタブのMaterialsの中のElement 0のマテリアルをLaser_tailにします。


Timeを0.5にします。
Colorクリックすると別でダイアログが出るので

右上のAlphaを0に


左下のColorを緑(好きな色で良いです)にします。

これでトレイルレンダラーの設定は終了。再生ボタンを押すとレーザーっぽい軌跡が表示されたと思います。

ここまで出来たらProjectタブにPrefabフォルダを新しく作成してHierarchyタブのLaser_prefabをProjectタブのPrefabフォルダに移動してHierarchyタブのLaser_prefabは削除しておきます。

次にレーザーの出現処理を追加します。
画面をクリックしたらクリックした場所にレーザーが発射されるようにしてみました。
Hierarchyタブに空のGameObjectを作成して名前をLaser_Createにします。
ProjectタブのScriptフォルダにCreate→C# Scriptで新しいスクリプトを作成。名前はLaser_Createにして下記のコードを追加します。

Laser_Create.cs

作成したLaser_CreateスクリプトをHierarchyタブにあるLaser_Createにアタッチします。

アタッチするとInspectorタブにLaser_prefabタブが出来ますので、ProjectタブのLaser_prefabをアタッチします。

この状態で再生ボタンを押すと、画面を左クリックするたびにレーザーが表示されるようになったと思いますが、レーザーが上まで行って消えてしまうと一瞬でテールも消えてしまうと思います。


これは先頭のレーザーが消えたときにトレイルレンダラーも消えてしまうために起こります。
なのでレーザーに親子関係をもたせてトレイルレンダラーは子オブジェクトに追加して親のオブジェクトが消えた瞬間に子を切り離して残しておくようにすると上手く行きました。

まず、ProjectタブのLaser_prefabをHierarchyタブにドラッグアンドドロップします。
HierarchyタブのLaser_prefabを右クリックして空のGameObjectを作成し名前をLaser_tailにしておきます。


Laser_tailに先ほどと同じようにトレイルレンダラーの設定をします。Laser_prefabの方のトレイルレンダラーは削除しておきましょう。


ProjectタブのScriptフォルダにCreate→C# Scriptで新しいスクリプトを作成。名前はLaser_Tailにして下記のコードを追加します。

Laser_Tail.cs

作成したLaser_TailスクリプトをHierarchyタブにあるLaser_Tailにアタッチします。


先程作成したLaser_move.csの16行目のコメントアウトしてある
//transform.DetachChildren();//親オブジェクトから子オブジェクトを解除
のコメントアウトを削除します。
このtransform.DetachChildren();関数で親オブジェクトから子オブジェクトを切り離せるみたいです。

HerarchyタブのLaser_prefabを選択してInspectorタブのPrefabのApplyを押すと変更した内容がProjectの方のPrefabに上書きされるので、HierarchyタブのLaser_prefabは削除しておきます。

この状態で再生すると、ちゃんと先頭のレーザーが消えてもテール部分は残り続けて良い感じでレーザーを表示する事が出来たと思います。
ただ、トレイルレンダラーにはコライダーなどの当たり判定を付けることが出来ないっぽい?ので自分で実装する必要がありそうなのでテール部分に当たり判定が付けたい場合は別の方法を考えた方が良いかもしれませんね。

それとScreenToWorldPoint関数を使うときにMain CameraのTagがMain Cameraになっていないと上手く動きませんでした。
どんなSTGを作ろうかなーと色々と考えているのですが、とりあえず烈火のレーザー的な自機弾を作成してみました。

ここで悩んだのが当たり判定です。このレーザーを実装するためには敵を倒す用の当たり判定とレーザーを敵の方向に向かわす為の当たり判定の2つが必要になります。
当たり判定自体はCollider命令で実装できるのですが2つ別々に判定する方法がわかりませんでした。

ググって見るとレーザーに親子関係を持たせてレーザー本体に敵との当たり判定、子の方に敵に向かわす為の判定を実装して別々のスクリプトで管理すると良さげ。

layer_bullet_laserが親でangle_collider_leftを子にします。
シーンの大きい緑枠が子の当たり判定で自機の前の小さい緑枠がレーザー本体の当たり判定として処理すれば上手く実装出来ました。

しかし更に問題が。レーザーは沢山発射されているのでちゃんと親の関数を呼び出す必要がありました。
これはtransform.root.gameObjectで親を取得出来るので、子のスクリプトで
GameObject X = transform.root.gameObject;
player_bullet_laser_move_right s = X.GetComponent<player_bullet_laser_move_right>();
s.Create_rad_ds(rad, 1f);
こんな感じで書くと子のスクリプトから親の関数を呼び出し出来ました。
1行目でXに親のオブジェクトを代入します。
2行目で親オブジェクトにアタッチされているスクリプトをsに代入します。
3行目でsにある関数Create_rad_dsを呼び出してレーザーの向きを変える感じです。

といった感じでなんとか実装は出来たのですが、これだけの事でも作るの相当大変でした。
出来ればギミックありありなSTGを作りたいなーと思っているのですが先は長そうです。。。
前回はUV展開時にスマートUV投影でUV展開していました。
この方法だとパーツがバラバラに展開されてしまって、繋げたい場所などで面倒な事になるんですよね。

円柱をスマートUV投影で展開すると筒の部分がバラバラになってしまいます。
かと言って普通にUV展開しようとしても上手く展開してくれないんですよね。

これは箱状の物を展開する時に切り開く場所を指定していないと、どこから展開して良いか判断出来ないのでおかしな事になっています。
なので切り開く場所を上手く指定してやると綺麗にUV展開出来るようになります。
この切り開く場所の指定をシームを付けると言うそうです。


シームを付けたい辺を選択してCtrl+Eを押すと出てくるメニューからシームを付けるを選択すると赤い線でシームが付きます。


こんな感じで上下の円と筒のにシームを付けました。


この状態でUV展開すると筒の部分が綺麗に展開されています。

といった感じなのですが複雑なモデルだとシームを付けながら作って行く方が良いのでしょうね。モデルによって普通のUV展開とスマートUV投影を使い分けるのが良いのかなぁと思いました。
Twitter
カレンダー
03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
最新コメント
[04/20 kt.]
[04/19 うぇむ]
[11/24 kt.]
[11/21 NONAME]
[11/24 kt.]
プロフィール
HN:
kt.
性別:
男性
自己紹介:
プログラミング経験は昔ファミリーベーシックでちょっとさわったくらい。
好きなSTGは、怒首領蜂大往生、エスプガルーダ(2)等の弾幕STGやら雷電シリーズなんかの非弾幕、バトルガレッガ、グラディウスシリーズ、R-TYPE等、STGなら何でも好きです。
音楽がカッコイイSTGが特に好きで、並木学氏は最高!
ブログ内検索
忍者ブログ [PR]