前回大量のオブジェクトを処理するときに考えた事(3)(連結リストについて) - kkana's blogもうこれでいいかなぁと思っていたところ
「粒子ごとに距離を測って加える力を計算するところ(連結リストをwhile文で回しているところ)でnew演算子を使わないようにするともっとカクカクしなくなる」と教えてもらったので また考え直しました。
大量ものを回しているときにnew しない!
できたもの↓
See the Pen ぶつからないように動くビークル(3) by kanaparty (@kanaparty) on CodePen.
(処理が早くなったのをいいことにしっぽを生やしました)
具体的に書き換えたところは以下です。 コメントアウトしてあるところが自作のベクトルクラスを呼び出しているところ。 他の粒子との距離を測るところでは、xとyの座標がわかってさえすればいいので わざわざベクトルクラスをインスタンス化しなくても良かったのでした。
separate() { // var sum = new Vector(0, 0); var sumX = 0; var sumY = 0; var count = 0; // var targetVehicle = currentVehicle; var targetVehicle = vehicles.first; while (targetVehicle) { // var diff = Vector.sub(this.vlocation, targetVehicle.vlocation); var diffx = this.vlocation.x - targetVehicle.vlocation.x; var diffy = this.vlocation.y - targetVehicle.vlocation.y; // var distance = diff.mag(); var distance = Math.sqrt(diffx * diffx + diffy * diffy); if (distance < this.separateRange && distance > 0) { // diff.div(distance); var weighting = distance * 4; diffx = diffx / weighting; diffy = diffy / weighting; // sum.add(diff); sumX += diffx; sumY += diffy; count++; } targetVehicle = targetVehicle.next; } if (count > 0) { // var steer = sum.sub(this.velocity); var steer = new Vector(sumX - this.velocity.x , sumY - this.velocity.y); this.acceleration.add(steer); } }
そんなに変わるのかな、と思って
new Vector()してるときとしていない時で粒子を2000個作って、
1フレームだけアニメーションさせて時間をはかった(おわりからループの始まりの時間を引いた)ところ、
newVectorしたとき
138 146 140 139 146 130 147 138 143 132
平均139.9しないとき
92 99 87 91 92 93 93 89 91 91
平均91.8
と、こんなに差がでました!!
インスタンス化するとそのぶんメモリが確保される(しないと最初から一つの場所しか参照しない)ので
処理の速度に違いが出るんじゃないのかということでした(?)
他に高速化のためにできそうなこと
- 一度計算した粒子間の距離をどこかに保存しておいて2重に計算しない
- 最初に生成する粒子の量を決めておいて、マウスを押したら死んだ粒子を生き返らせて(プロパティをセットし直して)使う(新しくnewで粒子を生成しない)
他に粒子系の処理の高速化を考えるなら・・・flashの作品を読む
粒子系の処理は昔flashでよく取り組まれていて、すでにいろんな方法で高速化が試されているらしい 。 なのでもっと突っ込んで考えたかったら beautifl.net
こういうところを参考にするといいそうです。
とはいえ考えすぎるのもよくない
しかしそんなにカクカクしなくなったのかは・・・・正直あまりわかりませんでした。。
高速化に取り組むのはいいけど深掘りすればするほどやれることが出てくるので
そのときどきに応じた対応をしたほうがよさそう