// ボーン //[Unity.Collections.ReadOnly] //public NativeArray<quaternion> boneRotList; // パーティクルごと public void Execute(int index) { var flag = flagList[index]; if (flag.IsValid() == false) { return; } // チームデータ int teamId = teamIdList[index]; var teamData = teamDataList[teamId]; // ここからは更新がある場合のみ実行(グローバルチームは除く) if (teamId != 0 && teamData.IsUpdate() == false) { return; } var oldpos = oldPosList[index]; var oldrot = oldRotList[index]; float3 nextPos = oldpos; quaternion nextRot = oldrot; //if (flag.IsCollider()) //{ // // コライダー // // todo:こっちのほうがよい? // nextPos = basePosList[index]; // nextRot = baseRotList[index]; //} if (flag.IsFixed()) { // キネマティックパーティクル // nextPos/nextRotが前回の姿勢 var oldNextPos = nextPosList[index]; var oldNextRot = nextRotList[index]; // OldPos/Rot から BasePos/Rot に step で補間して現在姿勢とする #if true // 高フレームレートで位置がスキップされてしまう問題の対処(1.8.3) float stime = teamData.startTime + updateDeltaTime * teamData.runCount; float oldtime = teamData.oldTime; float interval = teamData.time - oldtime; float step = math.saturate((stime - oldtime) / interval); #else float stime = teamData.startTime + updateDeltaTime * teamData.runCount; float oldtime = teamData.time - teamData.addTime; float step = math.saturate((stime - oldtime) / teamData.addTime); #endif nextPos = math.lerp(oldpos, basePosList[index], step); nextRot = math.slerp(oldrot, baseRotList[index], step); // 前回の姿勢をoldpos/rotとしてposList/rotListに格納する if (flag.IsCollider() && teamId == 0) { // グローバルコライダー // 移動量と回転量に制限をかける(1.7.5) // 制限をかけないと高速移動/回転時に遠く離れたパーティクルが押し出されてしまう問題が発生する。 oldpos = MathUtility.ClampDistance(nextPos, oldNextPos, Define.Compute.GlobalColliderMaxMoveDistance); oldrot = MathUtility.ClampAngle(nextRot, oldNextRot, math.radians(Define.Compute.GlobalColliderMaxRotationAngle)); } else { oldpos = oldNextPos; oldrot = oldNextRot; } // debug //nextPos = basePosList[index]; //nextRot = baseRotList[index]; } else { // 動的パーティクル var depth = depthList[index]; var maxVelocity = teamMaxVelocityList[teamId].Evaluate(depth); var drag = teamDragList[teamId].Evaluate(depth); var gravity = teamGravityList[teamId].Evaluate(depth); var mass = teamMassList[teamId].Evaluate(depth); var velocity = velocityList[index]; // チームスケール倍率 maxVelocity *= teamData.scaleRatio; // massは主に伸縮を中心に調整されるので、フォース適用時は少し調整する mass = (mass - 1.0f) * teamData.forceMassInfluence + 1.0f; // 安定化用の速度ウエイト velocity *= teamData.velocityWeight; // 最大速度 velocity = MathUtility.ClampVector(velocity, 0.0f, maxVelocity); // 空気抵抗(90ups基準) // 重力に影響させたくないので先に計算する(※通常はforce適用後に行うのが一般的) velocity *= math.pow(1.0f - drag, updatePower); // フォース // フォースは空気抵抗を無視して加算する float3 force = 0; // 重力 // 重力は質量に関係なく一定 #if false // 方向減衰 if (teamData.IsFlag(PhysicsManagerTeamData.Flag_DirectionalDamping) && teamData.directionalDampingBoneIndex >= 0) { float3 dampDir = math.mul(boneRotList[teamData.directionalDampingBoneIndex], teamData.directionalDampingLocalDir); var dot = math.dot(dampDir, new float3(0, -1, 0)) * 0.5f + 0.5f; // 1.0(0) - 0.5(90) - 0.0(180) var damp = teamDirectionalDampingList[teamId].Evaluate(dot); gravity *= damp; } #endif // (最後に質量で割るためここでは質量をかける) force.y += gravity * mass; // 外部フォース if (loopIndex == 0) { switch (teamData.forceMode) { case PhysicsManagerTeamData.ForceMode.VelocityAdd: force += teamData.impactForce; break; case PhysicsManagerTeamData.ForceMode.VelocityAddWithoutMass: force += teamData.impactForce * mass; break; case PhysicsManagerTeamData.ForceMode.VelocityChange: force += teamData.impactForce; velocity = 0; break; case PhysicsManagerTeamData.ForceMode.VelocityChangeWithoutMass: force += teamData.impactForce * mass; velocity = 0; break; } // 外力 force += teamData.externalForce; } // 外力チームスケール倍率 force *= teamData.scaleRatio; // 速度計算(質量で割る) velocity += (force / mass) * updateDeltaTime; // 速度を理想位置に反映させる nextPos = oldpos + velocity * updateDeltaTime; } // 予定座標更新 ============================================================== // 摩擦減衰 var friction = frictionList[index]; friction = friction * Define.Compute.FrictionDampingRate; frictionList[index] = friction; //frictionList[index] = 0; // 移動前の姿勢 posList[index] = oldpos; rotList[index] = oldrot; // 予測位置 nextPosList[index] = nextPos; nextRotList[index] = nextRot; // コリジョン用 //velocityList[index] = nextPos; }