コード例 #1
0
            // ボーン
            //[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;
            }