たすブログ

近況:4 告知:4 技術ブログ:2 な割合です

ProjectileMovementのホーミング使用時の注意点

ProjectileMovement、つかってますか?

簡単に弾が出せますし、

ホーミングもターゲットをちょちょいとつけるだけでやってくれて

非常に便利だなあと思ってたんですが

そのホーミングにちょっと罠がありました。

 

ホーミング

例えば敵の弾をプレーヤーに向けてホーミングしたい場合、

弾にProjectileMovementをつけてホーミングを有効にします。

 

で、その後BPでターゲットにプレーヤーをつけます。

f:id:tasuya:20180320155317p:plain

こんな感じ。

 

で、プレイすると良い感じにホーミングしてくれるんですが、

この形でホーミングをつけた敵の弾をDestroyすると、

内部的にホーミングが残ってしまうようです。

 

何がおきるか

残った場合、何がおきるかというと、

・プレーヤーが移動すると処理落ち

・プレーヤーを止めてしばらく待つと速度が戻る

という中々嫌な感じの影響が出ます。

Destroyしているので画面上に敵の弾はありませんが

プレーヤーが移動するとそこに向けてホーミングされるので処理落ち、

しばらく止まっていると直線に戻るので速度が戻る、ということだと思います。

 

原因

なーんでー?と思いながら調べてもわからず、ふと休憩した時に判明しました。

f:id:tasuya:20180320155318p:plain

HomingTargetComponentは弱参照じゃないと駄目みたいです。

カーソルのせた時のコメントに助けられました……

 

対処としては、

WeakObjectを渡してしまえば解決するので

WeakObjectが取れるLineTrace系を利用すればよさそうです。

f:id:tasuya:20180320155323p:plain

(すみません画像ミスありです。前後なのでForwardVectorに対して*10と*-10です)

対象の前後を取得してLineTraceForObjects等で確実に当てる形が

楽でいいかなと思いますが対象とLineTraceの間に何かが挟まってしまった場合

上手くいかないので、ObjectTypeを絞る等が必要です。

 

ちなみに普通の参照のまま対応できないかなーと

Destroy直前にTargetComponentをかえたり、ホーミングをオフにしたりと、

そもそもそれで対応できるなら多分Destroyでも解放されるよな、と

思いながら試した結果、特に変化はありませんでした。

素直にWeakObjectを入れてください。

 

 

問題になりにくい場合

参照が問題になるので、対象(この場合はプレーヤー)がDestroyされると

おそらく解放されます。

 

なので、

・レベル切り替えやプレーヤーのDestroyが適度にされる

・ホーミングの生成数がそもそもあまり多くない

といった場合は、問題が表面化まではいかないのかなと思います。

内部的には、たまってますが。

 

・「自分の攻撃」がホーミングで、あたった敵がDestroyされる

・ホーミングをDestroyしない

等は問題は発生しないと思いますので、

弾をプールする、等でも大丈夫かなと。 

 

WeakObject

プログラマUE4を使っている方にはこれ結構説明が難しいと思うんですが

誤解を招く覚悟で言うと

いつメモリを解放するかの話で

・Weakは使わなくなったらメモリ解放されやすい

・してほしくない場合も多々あるのでわかれてる

くらいで今日のところはお願いします。

 

WeakObjectがBP上で使われている箇所があるとわかった以上、

別の箇所でも処理がたまっていそうな挙動があった場合は

これを疑ってみてもいいのかなと。