예제 #1
0
        void Start()
        {
            rend = GetComponent <Renderer>();
            if (rend)
            {
                offMaterial = rend.sharedMaterial;
            }

            shatter = GetComponent <ShatterPart>();
        }
        public void Repair()
        {
            //Fix damaged parts
            for (int i = 0; i < damageParts.Length; i++)
            {
                if (damageParts[i].GetComponent <Motor>())
                {
                    damageParts[i].GetComponent <Motor>().health = 1;
                }

                if (damageParts[i].GetComponent <Transmission>())
                {
                    damageParts[i].GetComponent <Transmission>().health = 1;
                }
            }

            //Restore deformed meshes
            for (int i = 0; i < deformMeshes.Length; i++)
            {
                for (int j = 0; j < meshVertices[i].verts.Length; j++)
                {
                    meshVertices[i].verts[j] = meshVertices[i].initialVerts[j];
                }

                tempMeshes[i].vertices = meshVertices[i].verts;
                tempMeshes[i].RecalculateNormals();
                tempMeshes[i].RecalculateBounds();

                //Fix shattered parts
                ShatterPart fixedShatter = deformMeshes[i].GetComponent <ShatterPart>();
                if (fixedShatter)
                {
                    fixedShatter.shattered = false;

                    if (fixedShatter.brokenMaterial)
                    {
                        fixedShatter.rend.sharedMaterial = fixedShatter.initialMat;
                    }
                    else
                    {
                        fixedShatter.rend.enabled = true;
                    }
                }
            }

            //Restore deformed mesh colliders
            for (int i = 0; i < deformColliders.Length; i++)
            {
                for (int j = 0; j < colVertices[i].verts.Length; j++)
                {
                    colVertices[i].verts[j] = colVertices[i].initialVerts[j];
                }

                tempCols[i].vertices          = colVertices[i].verts;
                deformColliders[i].sharedMesh = null;
                deformColliders[i].sharedMesh = tempCols[i];
            }

            //Fix displaced parts
            Suspension fixedSus;
            Transform  curDisplacePart;

            for (int i = 0; i < displaceParts.Length; i++)
            {
                curDisplacePart = displaceParts[i];
                curDisplacePart.localPosition = initialPartPositions[i];

                if (curDisplacePart.GetComponent <DetachablePart>())
                {
                    curDisplacePart.GetComponent <DetachablePart>().Reattach();
                }
                else if (curDisplacePart.parent.GetComponent <DetachablePart>())
                {
                    curDisplacePart.parent.GetComponent <DetachablePart>().Reattach();
                }

                fixedSus = curDisplacePart.GetComponent <Suspension>();
                if (fixedSus)
                {
                    curDisplacePart.localRotation = fixedSus.initialRotation;
                    fixedSus.jammed = false;

                    foreach (SuspensionPart curPart in fixedSus.movingParts)
                    {
                        if (curPart.connectObj && !curPart.isHub && !curPart.solidAxle)
                        {
                            if (!curPart.connectObj.GetComponent <SuspensionPart>())
                            {
                                curPart.connectPoint = curPart.initialConnectPoint;
                            }
                        }
                    }
                }
            }

            //Fix wheels
            foreach (Wheel curWheel in vp.wheels)
            {
                curWheel.Reattach();
                curWheel.FixTire();
                curWheel.damage = 0;
            }

            //Fix hover wheels
            foreach (HoverWheel curHoverWheel in vp.hoverWheels)
            {
                curHoverWheel.Reattach();
            }
        }
        //Where the damage is actually applied
        void DamageApplication(Vector3 damagePoint, Vector3 damageForce, float damageForceLimit, Vector3 surfaceNormal, ContactPoint colPoint, bool useContactPoint)
        {
            float          colMag        = Mathf.Min(damageForce.magnitude, maxCollisionMagnitude) * (1 - strength) * damageFactor; //Magnitude of collision
            float          clampedColMag = Mathf.Pow(Mathf.Sqrt(colMag) * 0.5f, 1.5f);                                              //Clamped magnitude of collision
            Vector3        clampedVel    = Vector3.ClampMagnitude(damageForce, damageForceLimit);                                   //Clamped velocity of collision
            Vector3        normalizedVel = damageForce.normalized;
            float          surfaceDot;                                                                                              //Dot production of collision velocity and surface normal
            float          massFactor = 1;                                                                                          //Multiplier for damage based on mass of other rigidbody
            Transform      curDamagePart;
            float          damagePartFactor;
            MeshFilter     curDamageMesh;
            Transform      curDisplacePart;
            Transform      seamKeeper = null;//Transform for maintaining seams on shattered parts
            Vector3        seamLocalPoint;
            Vector3        vertProjection;
            Vector3        translation;
            Vector3        clampedTranslation;
            Vector3        localPos;
            float          vertDist;
            float          distClamp;
            DetachablePart detachedPart;
            Suspension     damagedSus;

            //Get mass factor for multiplying damage
            if (useContactPoint)
            {
                damagePoint   = colPoint.point;
                surfaceNormal = colPoint.normal;

                if (colPoint.otherCollider.attachedRigidbody)
                {
                    massFactor = Mathf.Clamp01(colPoint.otherCollider.attachedRigidbody.mass / rb.mass);
                }
            }

            surfaceDot = Mathf.Clamp01(Vector3.Dot(surfaceNormal, normalizedVel)) * (Vector3.Dot((tr.position - damagePoint).normalized, normalizedVel) + 1) * 0.5f;

            //Damage damageable parts
            for (int i = 0; i < damageParts.Length; i++)
            {
                curDamagePart    = damageParts[i];
                damagePartFactor = colMag * surfaceDot * massFactor * Mathf.Min(clampedColMag * 0.01f, (clampedColMag * 0.001f) / Mathf.Pow(Vector3.Distance(curDamagePart.position, damagePoint), clampedColMag));

                //Damage motors
                Motor damagedMotor = curDamagePart.GetComponent <Motor>();
                if (damagedMotor)
                {
                    damagedMotor.health -= damagePartFactor * (1 - damagedMotor.strength);
                }

                //Damage transmissions
                Transmission damagedTransmission = curDamagePart.GetComponent <Transmission>();
                if (damagedTransmission)
                {
                    damagedTransmission.health -= damagePartFactor * (1 - damagedTransmission.strength);
                }
            }

            //Deform meshes
            for (int i = 0; i < deformMeshes.Length; i++)
            {
                curDamageMesh      = deformMeshes[i];
                localPos           = curDamageMesh.transform.InverseTransformPoint(damagePoint);
                translation        = curDamageMesh.transform.InverseTransformDirection(clampedVel);
                clampedTranslation = Vector3.ClampMagnitude(translation, clampedColMag);

                //Shatter parts that can shatter
                ShatterPart shattered = curDamageMesh.GetComponent <ShatterPart>();
                if (shattered)
                {
                    seamKeeper = shattered.seamKeeper;
                    if (Vector3.Distance(curDamageMesh.transform.position, damagePoint) < colMag * surfaceDot * 0.1f * massFactor && colMag * surfaceDot * massFactor > shattered.breakForce)
                    {
                        shattered.Shatter();
                    }
                }

                //Actual deformation
                if (translation.sqrMagnitude > 0 && strength < 1)
                {
                    for (int j = 0; j < meshVertices[i].verts.Length; j++)
                    {
                        vertDist  = Vector3.Distance(meshVertices[i].verts[j], localPos);
                        distClamp = (clampedColMag * 0.001f) / Mathf.Pow(vertDist, clampedColMag);

                        if (distClamp > 0.001f)
                        {
                            damagedMeshes[i] = true;
                            if (seamKeeper == null || seamlessDeform)
                            {
                                vertProjection            = seamlessDeform ? Vector3.zero : Vector3.Project(normalizedVel, meshVertices[i].verts[j]);
                                meshVertices[i].verts[j] += (clampedTranslation - vertProjection * (usePerlinNoise ? 1 + Mathf.PerlinNoise(meshVertices[i].verts[j].x * 100, meshVertices[i].verts[j].y * 100) : 1)) * surfaceDot * Mathf.Min(clampedColMag * 0.01f, distClamp) * massFactor;
                            }
                            else
                            {
                                seamLocalPoint            = seamKeeper.InverseTransformPoint(curDamageMesh.transform.TransformPoint(meshVertices[i].verts[j]));
                                meshVertices[i].verts[j] += (clampedTranslation - Vector3.Project(normalizedVel, seamLocalPoint) * (usePerlinNoise ? 1 + Mathf.PerlinNoise(seamLocalPoint.x * 100, seamLocalPoint.y * 100) : 1)) * surfaceDot * Mathf.Min(clampedColMag * 0.01f, distClamp) * massFactor;
                            }
                        }
                    }
                }
            }

            seamKeeper = null;

            //Deform mesh colliders
            for (int i = 0; i < deformColliders.Length; i++)
            {
                localPos           = deformColliders[i].transform.InverseTransformPoint(damagePoint);
                translation        = deformColliders[i].transform.InverseTransformDirection(clampedVel);
                clampedTranslation = Vector3.ClampMagnitude(translation, clampedColMag);

                if (translation.sqrMagnitude > 0 && strength < 1)
                {
                    for (int j = 0; j < colVertices[i].verts.Length; j++)
                    {
                        vertDist  = Vector3.Distance(colVertices[i].verts[j], localPos);
                        distClamp = (clampedColMag * 0.001f) / Mathf.Pow(vertDist, clampedColMag);

                        if (distClamp > 0.001f)
                        {
                            damagedCols[i]           = true;
                            colVertices[i].verts[j] += clampedTranslation * surfaceDot * Mathf.Min(clampedColMag * 0.01f, distClamp) * massFactor;
                        }
                    }
                }
            }


            //Displace parts
            for (int i = 0; i < displaceParts.Length; i++)
            {
                curDisplacePart    = displaceParts[i];
                translation        = clampedVel;
                clampedTranslation = Vector3.ClampMagnitude(translation, clampedColMag);

                if (translation.sqrMagnitude > 0 && strength < 1)
                {
                    vertDist  = Vector3.Distance(curDisplacePart.position, damagePoint);
                    distClamp = (clampedColMag * 0.001f) / Mathf.Pow(vertDist, clampedColMag);

                    if (distClamp > 0.001f)
                    {
                        curDisplacePart.position += clampedTranslation * surfaceDot * Mathf.Min(clampedColMag * 0.01f, distClamp) * massFactor;

                        //Detach detachable parts
                        if (curDisplacePart.GetComponent <DetachablePart>())
                        {
                            detachedPart = curDisplacePart.GetComponent <DetachablePart>();

                            if (colMag * surfaceDot * massFactor > detachedPart.looseForce && detachedPart.looseForce >= 0)
                            {
                                detachedPart.initialPos = curDisplacePart.localPosition;
                                detachedPart.Detach(true);
                            }
                            else if (colMag * surfaceDot * massFactor > detachedPart.breakForce)
                            {
                                detachedPart.Detach(false);
                            }
                        }
                        //Maybe the parent of this part is what actually detaches, useful for displacing compound colliders that represent single detachable objects
                        else if (curDisplacePart.parent.GetComponent <DetachablePart>())
                        {
                            detachedPart = curDisplacePart.parent.GetComponent <DetachablePart>();

                            if (!detachedPart.detached)
                            {
                                if (colMag * surfaceDot * massFactor > detachedPart.looseForce && detachedPart.looseForce >= 0)
                                {
                                    detachedPart.initialPos = curDisplacePart.parent.localPosition;
                                    detachedPart.Detach(true);
                                }
                                else if (colMag * surfaceDot * massFactor > detachedPart.breakForce)
                                {
                                    detachedPart.Detach(false);
                                }
                            }
                            else if (detachedPart.hinge)
                            {
                                detachedPart.displacedAnchor += curDisplacePart.parent.InverseTransformDirection(clampedTranslation * surfaceDot * Mathf.Min(clampedColMag * 0.01f, distClamp) * massFactor);
                            }
                        }

                        //Damage suspensions and wheels
                        damagedSus = curDisplacePart.GetComponent <Suspension>();
                        if (damagedSus)
                        {
                            if ((!damagedSus.wheel.grounded && ignoreGroundedWheels) || !ignoreGroundedWheels)
                            {
                                curDisplacePart.RotateAround(damagedSus.tr.TransformPoint(damagedSus.damagePivot), Vector3.ProjectOnPlane(damagePoint - curDisplacePart.position, -translation.normalized), clampedColMag * surfaceDot * distClamp * 20 * massFactor);

                                damagedSus.wheel.damage += clampedColMag * surfaceDot * distClamp * 10 * massFactor;

                                if (clampedColMag * surfaceDot * distClamp * 10 * massFactor > damagedSus.jamForce)
                                {
                                    damagedSus.jammed = true;
                                }

                                if (clampedColMag * surfaceDot * distClamp * 10 * massFactor > damagedSus.wheel.detachForce)
                                {
                                    damagedSus.wheel.Detach();
                                }

                                foreach (SuspensionPart curPart in damagedSus.movingParts)
                                {
                                    if (curPart.connectObj && !curPart.isHub && !curPart.solidAxle)
                                    {
                                        if (!curPart.connectObj.GetComponent <SuspensionPart>())
                                        {
                                            curPart.connectPoint += curPart.connectObj.InverseTransformDirection(clampedTranslation * surfaceDot * Mathf.Min(clampedColMag * 0.01f, distClamp) * massFactor);
                                        }
                                    }
                                }
                            }
                        }

                        //Damage hover wheels
                        HoverWheel damagedHoverWheel = curDisplacePart.GetComponent <HoverWheel>();
                        if (damagedHoverWheel)
                        {
                            if ((!damagedHoverWheel.grounded && ignoreGroundedWheels) || !ignoreGroundedWheels)
                            {
                                if (clampedColMag * surfaceDot * distClamp * 10 * massFactor > damagedHoverWheel.detachForce)
                                {
                                    damagedHoverWheel.Detach();
                                }
                            }
                        }
                    }
                }
            }
        }