예제 #1
0
    // Update is called once per frame
    void FixedUpdate()
    {
        float leftTrig  = 0.0f;
        float rightTrig = 0.0f;

        if (leftTrackedObject != null && leftTrackedObject.isActiveAndEnabled)
        {
            // The trigger button
            leftTrig = leftController.GetAxis(Valve.VR.EVRButtonId.k_EButton_Axis1).x;
        }

        if (rightTrackedObject != null && rightTrackedObject.isActiveAndEnabled)
        {
            // The trigger button
            rightTrig = rightController.GetAxis(Valve.VR.EVRButtonId.k_EButton_Axis1).x;
        }

        if (leftTrig > 0.2f)
        {
            rigidBody.AddForceAtPosition(leftTrackedObject.transform.forward * power * leftTrig, leftTrackedObject.transform.position);
        }
        else
        {
        }
        leftEngine.GetComponent <JetFire>().fire = leftTrig;

        float max = 3999;

        SteamVR_Controller.Input(
            SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Leftmost)
            ).TriggerHapticPulse((ushort)(leftTrig * max));
        SteamVR_Controller.Input(
            SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Rightmost)
            ).TriggerHapticPulse((ushort)(rightTrig * max));


        rightEngine.GetComponent <JetFire>().fire = rightTrig;

        if (rightTrig > 0.2f)
        {
            rigidBody.AddForceAtPosition(rightTrackedObject.transform.forward * power * rightTrig, rightTrackedObject.transform.position);
        }
        else
        {
        }

        rigidBody.velocity = Vector3.ClampMagnitude(rigidBody.velocity, maxSpeed);

        //rigidBody.velocity = Vector3.ClampMagnitude(rigidBody.velocity, 10f);

        /*
         * if (leftTrig > 0.2f && rightTrig > 0.2f)
         * {
         *  rigidBody.AddForce(head.transform.forward * power * 10);
         * }
         * else if (leftTrig > 0.2f)
         * {
         *  desiredYaw *= Quaternion.AngleAxis(leftTrig * 0.5f, Vector3.up);
         * }
         * else if (rightTrig > 0.2f)
         * {
         *  desiredYaw *= Quaternion.AngleAxis(rightTrig * 0.5f, -Vector3.up);
         * }
         *
         * float currentYaw = transform.rotation.eulerAngles.y;
         * transform.rotation = Quaternion.Slerp(transform.rotation, desiredYaw, Time.deltaTime);
         */
    }
예제 #2
0
 private void pushRigidBody(Rigidbody rb)
 {
     rb.AddForceAtPosition(mainCamera.transform.forward * power, hit.point, ForceMode.Impulse);
     UIController.AddScoreUIForFPP(1);
 }
예제 #3
0
 // Update is called once per frame
 void Update()
 {
     rb.AddForceAtPosition(Vector3.down * carConfig.downForce, transform.position + transform.forward, ForceMode.Acceleration);
     rb.AddForceAtPosition(Vector3.down * carConfig.downForce, transform.position - transform.forward, ForceMode.Acceleration);
 }
예제 #4
0
파일: Rope.cs 프로젝트: mrdivdiz/bpvita
    private void PullEndpoints()
    {
        float num = 0f;

        for (int i = 1; i < this.m_nodes.Count; i++)
        {
            Rigidbody rigidbody  = this.m_nodes[i - 1].rigidbody;
            Rigidbody rigidbody2 = this.m_nodes[i].rigidbody;
            if (rigidbody && rigidbody2)
            {
                float num2 = Vector3.Distance(rigidbody.position, rigidbody2.position);
                if (i > 1 && i < this.m_nodes.Count - 2)
                {
                    if (num2 > 1.25f)
                    {
                        this.Cut(i);
                        return;
                    }
                }
                else if (num2 > 1.75f)
                {
                    this.Cut(i);
                    return;
                }
                num += num2;
            }
        }
        float num3 = 0.5f * (float)this.m_nodes.Count;
        float num4 = num / (1.18f * num3) - 1f;
        float num5 = 0.4f;

        num4 = num5 * this.ResponseCurve(num4 / num5);
        num4 = Mathf.Clamp(num4, 0f, num5);
        float num6 = num4 - this.m_previousStretchFactor;

        this.m_previousStretchFactor = num4;
        if (num > 1.18f * num3)
        {
            Rigidbody rigidbody3 = this.m_nodes[0].rigidbody;
            Rigidbody rigidbody4 = this.m_nodes[1].rigidbody;
            Vector3   position   = rigidbody3.position;
            Vector3   position2  = rigidbody4.position;
            if (num6 < 0f)
            {
                num4 *= 0.7f;
            }
            float num7 = 750f;
            float num8 = num7 * num4;
            num8 = Mathf.Clamp(num8, 0f, 300f);
            Vector3 force = num8 * (position2 - position).normalized;
            if (this.LeftPart)
            {
                rigidbody3.AddForceAtPosition(force, position, ForceMode.Force);
            }
            rigidbody3 = this.m_nodes[this.m_nodes.Count - 1].rigidbody;
            rigidbody4 = this.m_nodes[this.m_nodes.Count - 2].rigidbody;
            position   = rigidbody3.position;
            position2  = rigidbody4.position;
            force      = num8 * (position2 - position).normalized;
            if (this.RightPart)
            {
                rigidbody3.AddForceAtPosition(force, position, ForceMode.Force);
            }
        }
    }
예제 #5
0
    /// <summary>
    /// Handles the gravity and hovering for the ship.
    /// </summary>
    public void Gravity()
    {
        // Reset gravity/magstrip
        bShipIsGrounded   = false;
        bShipIsOnMagStrip = false;

        // Increase the rideheight slightly (keeps the ship at the actual wanted height)
        float rideHeight = GlobalSettings.shipRideHeight * 1.2f;

        // Pitching
        if (controller.inputPitch != 0)
        {
            shipPitchAmount = Mathf.Lerp(shipPitchAmount, controller.inputPitch * GlobalSettings.shipPitchGroundAmount, Time.deltaTime * GlobalSettings.shipPitchDamping);
        }
        else
        {
            shipPitchAmount = Mathf.Lerp(shipPitchAmount, 0.0f, Time.deltaTime * GlobalSettings.shipPitchDamping);
        }
        shipBody.AddTorque(transform.right * (shipPitchAmount * 10));

        // Get the current class and set the gravity multipliers
        float gravityMul = 0;
        float trackGrav  = 0;
        float flightGrav = 0;

        switch (eventSpeedClass)
        {
        case GlobalSettings.SpeedClasses.D:
            // Gravity Multiplier
            gravityMul = GlobalSettings.airGravityMulD;
            // Track Gravity
            trackGrav = GlobalSettings.shipTrackGravityD;
            // Flight Gravity
            flightGrav = GlobalSettings.shipFlightGravityD;
            break;

        case GlobalSettings.SpeedClasses.C:
            // Gravity Multiplier
            gravityMul = GlobalSettings.airGravityMulC;
            // Track Gravity
            trackGrav = GlobalSettings.shipTrackGravityC;
            // Flight Gravity
            flightGrav = GlobalSettings.shipFlightGravityC;
            break;

        case GlobalSettings.SpeedClasses.B:
            // Gravity Multiplier
            gravityMul = GlobalSettings.airGravityMulB;
            // Track Gravity
            trackGrav = GlobalSettings.shipTrackGravityB;
            // Flight Gravity
            flightGrav = GlobalSettings.shipFlightGravityB;
            break;

        case GlobalSettings.SpeedClasses.A:
            // Gravity Multiplier
            gravityMul = GlobalSettings.airGravityMulA;
            // Track Gravity
            trackGrav = GlobalSettings.shipTrackGravityA;
            // Flight Gravity
            flightGrav = GlobalSettings.shipFlightGravityA;
            break;

        case GlobalSettings.SpeedClasses.AP:
            // Gravity Multiplier
            gravityMul = GlobalSettings.airGravityMulAP;
            // Track Gravity
            trackGrav = GlobalSettings.shipTrackGravityAP;
            // Flight Gravity
            flightGrav = GlobalSettings.shipFlightGravityAP;
            break;

        case GlobalSettings.SpeedClasses.APP:
            // Gravity Multiplier
            gravityMul = GlobalSettings.airGravityMulAPP;
            // Track Gravity
            trackGrav = GlobalSettings.shipTrackGravityAPP;
            // Flight Gravity
            flightGrav = GlobalSettings.shipFlightGravityAPP;
            break;
        }

        // Create hover points list
        List <Vector3> hoverPoints = new List <Vector3>();
        // Get a slightly smaller area of the ship size
        Vector2 hoverArea = new Vector2(settings.physColliderSize.x / 2, settings.physColliderSize.z / 2.05f);

        // Add hover points
        hoverPoints.Add(transform.TransformPoint(-hoverArea.x, Mathf.Clamp(shipPitchAmount, 0.0f, 0.5f), hoverArea.y));   // Front Left
        hoverPoints.Add(transform.TransformPoint(hoverArea.x, Mathf.Clamp(shipPitchAmount, 0.0f, 0.5f), hoverArea.y));    // Front Right
        hoverPoints.Add(transform.TransformPoint(hoverArea.x, Mathf.Clamp(-shipPitchAmount, 0.0f, 0.7f), -hoverArea.y));  // Back Right
        hoverPoints.Add(transform.TransformPoint(-hoverArea.x, Mathf.Clamp(-shipPitchAmount, 0.0f, 0.7f), -hoverArea.y)); // Back Left

        // Run through each hover point and apply hover forces if needed
        for (int i = 0; i < hoverPoints.Count; i++)
        {
            // Bitshift track floor and mag lock layers into a new integer for the ship to only check for those two collision layers
            int trackFloorMask = 1 << LayerMask.NameToLayer("TrackFloor") | 1 << LayerMask.NameToLayer("Maglock");
            // Create raycasthit to store hit data into
            RaycastHit hoverHit;
            // Raycast down for track
            if (Physics.Raycast(hoverPoints[i], -transform.up, out hoverHit, rideHeight, trackFloorMask))
            {
                // Get the distance to the ground
                float dist = hoverHit.distance;

                // Normalize the distance into a compression ratio
                float compressionRatio = ((dist / rideHeight) - 1) * -1;

                // Get the velocity at the hover point
                Vector3 hoverVel = shipBody.GetPointVelocity(hoverPoints[i]);

                // Project the velocity onto the ships up vector
                Vector3 projForce = Vector3.Project(hoverVel, transform.up);

                // Check to see if the ship is on a magstrip
                if (hoverHit.collider.gameObject.layer == LayerMask.NameToLayer("Maglock"))
                {
                    bShipIsOnMagStrip = true;
                }

                /* Calculate force needed to push ship away from track */
                // Set a force multiplier
                float forceMult = 5;
                // Calcaulate a ratio to multiply the compression ratio by (drasticly increases the hover force as it gets closer to the track)
                float forceRatio = ((dist / 2) / (rideHeight / 2) - 1) * -forceMult;
                // Clamp the ratio
                forceRatio = Mathf.Clamp(forceRatio, 2.0f, 10.0f);
                // Create the new force
                float force = 200.0f * (compressionRatio * forceRatio);

                /* Calculate damping amount to bring the ship to rest quicker */
                // Set a damping multiplier
                float dampMult = 6.5f;
                // Calculate a ratio to multiply the compression ratio by
                float dampRatio = ((dist / 2) / (rideHeight / 2) - 1) * -dampMult;
                // Clamp the ratio
                dampRatio = Mathf.Clamp(dampRatio, 1.0f, 5.5f);
                // Clamp the compression ratio, min being the base damp amount
                float clampedCR = Mathf.Clamp(compressionRatio, 0.5f, 1.0f);

                // Get the landing rebound to dampen forces straight after a long fall (stops the ship rebounding high off the track)
                float reboundDamper = Mathf.Clamp(shipReboundLand * 15, 1.0f, Mathf.Infinity);
                // Create the new damping force
                float damping = (1 * (clampedCR * dampRatio) * reboundDamper);

                // If the ship is over a magstrip then we want the ship to act a bit differently
                if (bShipIsOnMagStrip)
                {
                    // Calculate how strong the magstrip is based on the ships current angular velocity and speed
                    float magStrength = Mathf.Abs(transform.InverseTransformDirection(shipBody.angularVelocity).x *Time.deltaTime)
                                        * Mathf.Abs(transform.InverseTransformDirection(shipBody.velocity).z *Time.deltaTime);
                    // Multiply the strength as the above calculate will result in a terrible lock strength
                    magStrength *= 1000;
                    // Clamp the strength so it can't be too strong
                    magStrength = Mathf.Clamp(magStrength, 0.0f, (transform.InverseTransformDirection(shipBody.velocity).z *Time.deltaTime) * 3.8f);

                    // Set new force and damping multipliers
                    force   = (trackGrav * (5.0f + magStrength));
                    damping = 2f;

                    // Apply the magstrip lock force
                    shipBody.AddForceAtPosition(-transform.up * (trackGrav * (magStrength * 4.0f)), hoverPoints[i], ForceMode.Acceleration);
                }

                // Calculate the suspension force
                Vector3 suspensionForce = transform.up * compressionRatio * force;

                // Now apply damping
                Vector3 dampedForce = suspensionForce - (projForce * damping);

                // Finally, apply the force
                shipBody.AddForceAtPosition(dampedForce, hoverPoints[i], ForceMode.Acceleration);

                // Set the grounded boolean to true
                bShipIsGrounded = true;

                // Debug line
                if (bDebugVisualizeHovering)
                {
                    Debug.DrawLine(hoverPoints[i], hoverHit.point);
                }

                // Force feedback
                if (dist < rideHeight * 0.6f)
                {
                    vibrationManager.vibLeftMotor  = 0.3f;
                    vibrationManager.vibRightMotor = 0.3f;
                    vibrationManager.timerMotor    = 1.1f;
                }
            }
        }

        /* If the ship is grounded then we also want to have the ship be pulled down by gravity
         * We want to do another raycast for the trackfloor layer only from the centre of the ship
         * then calculate everything from that.
         *
         * Don't worry, we are only casting for one layer over a short distance, this isn't very
         * expensive to do. */
        // Create raycasthit to store hit data into
        RaycastHit centreHit;

        // Raycast down
        if (Physics.Raycast(transform.position, -transform.up, out centreHit, rideHeight, 1 << LayerMask.NameToLayer("TrackFloor")))
        {
            // Use a dot product to find out how much we need to rotate the ship to get it to face down
            Vector3 trackRot = transform.forward - (Vector3.Dot(transform.forward, centreHit.normal) * centreHit.normal);
            // Use the track rotation to calculate how much we are going to rotate the ship
            float rotAmount = (trackRot.x * trackRot.z) * (Mathf.Clamp(Mathf.Abs(trackRot.y), 0.0f, 0.1f) * 10);
            // Increase the rotation amount as the ship speeds up
            float rotForce = 20 + (transform.InverseTransformDirection(shipBody.velocity).z *Time.deltaTime) * 1.2f;
            // Apply the rotation
            transform.Rotate(Vector3.up * (rotAmount * Time.deltaTime) * rotForce);

            // Apply gravity force
            shipBody.AddForce(new Vector3(centreHit.normal.x, 0, centreHit.normal.z) * (Mathf.Abs(trackRot.x)) * 22);
        }


        /* We also want to check for pads on the track. We'll do exactly the same as above to do this.
         * Also we can recycle the centrehit variable! */
        // Bitshift pads into integer
        int padMask = 1 << LayerMask.NameToLayer("SpeedPad") | 1 << LayerMask.NameToLayer("WeaponPad");

        // Raycast down
        if (Physics.Raycast(transform.position, -transform.up, out centreHit, rideHeight + 2, padMask))
        {
            // If the ship hits a speed pad then apply the appropiate force
            if (centreHit.collider.gameObject.layer == LayerMask.NameToLayer("SpeedPad"))
            {
                // Get the pad's forward direction
                speedPadDirection = centreHit.collider.gameObject.transform.right * GlobalSettings.speedPadAmount;
                // Set the ships boost timer
                shipBoostTimer = GlobalSettings.speedPadTime;
                // Set boosting to true
                bShipIsBoosting = true;

                // If we havn't hit this pad already, play the boost sound
                if (!bShipHitPad)
                {
                    bShipHitPad = true;

                    // Get sound to play
                    AudioClip boostSFX = Resources.Load("Audio/Ships/BoostSpeedPad") as AudioClip;

                    // Play the sound
                    PlayOneShot.PlayShot("BoostSFX", 1.0f, 1.0f, 50.0f, 500.0f, transform, transform.position, boostSFX);
                }
            }
        }
        else
        {
            // We are not hitting a pad, set the hitting pad boolean to false
            bShipHitPad = false;
        }

        // If the boost timer is over zero then we want to decrease it and apply any boost the ship has
        if (shipBoostTimer > 0)
        {
            // Decrease timer
            shipBoostTimer -= Time.deltaTime;
            // Apply pad boost
            shipBody.AddForce(speedPadDirection, ForceMode.Acceleration);
        }
        else
        {
            // Make sure that the pad hit boolean is no longer true
            bShipHitPad = false;

            // Override boost if the ship has boost power from a barrel rol
            if (shipBRBoostTimer > 0)
            {
                bShipIsBoosting = true;
                // Apply the barrel roll boost
                shipBody.AddForce(transform.forward * settings.engineTurbo, ForceMode.Acceleration);
            }
            else
            {
                // Otherwise the boosting is set to false
                bShipIsBoosting = false;
            }
        }

        // Allow the turbo pickup to override the boost
        if (bShipBoostingOverride)
        {
            bShipIsBoosting = true;
        }

        // Boosting Force Feedback
        if (bShipIsBoosting)
        {
            vibrationManager.timerMotor    = 1.1f;
            vibrationManager.vibLeftMotor  = 0.4f;
            vibrationManager.vibRightMotor = 0.4f;
        }

        /* And finally we want to apply gravity, we want to swap out the gravity between two different variables
         * which allows the ship to feel much lighter on the track, this also makes the hovering feel much better too */
        // Check to see if the ship is grounded
        if (bShipIsGrounded)
        {
            // If the ship is on a magstrip then the gravity wants to be heavier
            if (bShipIsOnMagStrip)
            {
                // Set gravity
                shipGravityForce = -transform.up * (trackGrav * 5);
            }
            else
            {
                // Set gravity
                shipGravityForce = -transform.up * trackGrav;
            }

            // Set the rebound jump time so the stick force is always maxed when the ship enters flight
            shipReboundJump = settings.agReboundJumpTime;

            // Decrease the rebound land
            shipReboundLand -= Time.deltaTime;
        }
        else
        {
            // Set the gravity
            shipGravityForce = Vector3.down * (flightGrav * gravityMul);

            // Decrease the jump
            shipReboundJump -= Time.deltaTime;
            // Apply the stick force
            if (shipReboundJump > 0)
            {
                // Apply the force to keep the ship grounded
                shipBody.AddForce(Vector3.down * ((10 * GlobalSettings.shipNormalGravity) * settings.agRebound), ForceMode.Acceleration);
            }

            // Set rebound to zero if it has gone under zero
            if (shipReboundLand < 0)
            {
                shipReboundLand = 0;
            }

            // Increase the rebound land
            shipReboundLand += Time.deltaTime;
            // Clamp the rebound land
            if (shipReboundLand > settings.agReboundLanding)
            {
                shipReboundLand = settings.agReboundLanding;
            }

            // Slowly rotate the ship forward
            transform.Rotate(Vector3.right * 0.05f);
        }

        // And finally, apply the gravity
        shipBody.AddForce(shipGravityForce, ForceMode.Acceleration);
    }
예제 #6
0
    /*This is the die effect. A simple-complicated effect of subdivide any big part of the player.
     * Only works for this "marvellous designed" game character ;) Assume that it works of everything made of cubes and have no children under a mesh renderer !
     * This effect is pretty heavy to process because of the high number of instance done, and should make disappear the part of the body quickly to avoid too much object in the scene, or at least cut the physics.
     **/
    void DieEffect(Bullet bullet)
    {
        //First we search all the gameObject that compose the player. We don't take the root.
        SearchAllGameobject(transform.GetChild(0));

        //Calculation of the volume represented by the given subdivision
        float volumeSubdivision = Mathf.Pow(sizeSubdivision, 3f);

        int subDivisionMaxCount = 0;
        int subDivisionCount    = 0;

        BloodManager.instance.setTimeBeforeDisappear(timeBeforeDivideOnDeath);
        BloodManager.instance.registerNewBloodMaterial(new Material(bloodMaterial));

        foreach (GameObject gameObj in physicalObjects)
        {
            //We just move the object to the instance manager, to clean the scene
            InstanceManager.instance.MoveTo(InstanceManager.InstanceType.Graphics, gameObj);

            //We add box and rigidbody to this object, we set the layer
            BoxCollider boxObj = gameObj.AddComponent <BoxCollider>();
            boxObj.isTrigger = false;
            Rigidbody rigidObj = gameObj.AddComponent <Rigidbody>();
            gameObj.layer = LayerMask.NameToLayer("Default");

            //We disable the box collider and the rigidbody for now
            boxObj.enabled       = false;
            rigidObj.useGravity  = false;
            rigidObj.isKinematic = true;

            //Here's the touchy part : If the object can contains at least 4 subdivision, we'll devide it
            if (gameObj.transform.lossyScale.x * gameObj.transform.lossyScale.y * gameObj.transform.lossyScale.z >= 4f * volumeSubdivision && gameObj.tag != "DontSubdivide")
            {
                //First we calculate how many subdivision we are going to have on each side x, y, z. We ceil it to avoid a 0 case.
                Vector3 maxSubdivision = gameObj.transform.lossyScale / sizeSubdivision;
                maxSubdivision = new Vector3(Mathf.Ceil(maxSubdivision.x), Mathf.Ceil(maxSubdivision.y), Mathf.Ceil(maxSubdivision.z));

                //To simply the maths, we'll use the child property to adjust local position. The local position for one of the cube angle is -0.5, -0.5, -0.5
                //We had the half of a subdivision size to avoid a translation for instancing the small object (if not, the subdivision will be center at the corner, which is not good)
                Vector3 positionOriginSubdivision = (Vector3.one * -0.5f) + new Vector3(1f / (maxSubdivision.x * 2f), 1f / (maxSubdivision.y * 2f), 1f / (maxSubdivision.z * 2f));

                subDivisionCount = 0;

                //We are rolling all subdivision
                for (int x = 0; x < maxSubdivision.x; x++)
                {
                    for (int y = 0; y < maxSubdivision.y; y++)
                    {
                        for (int z = 0; z < maxSubdivision.z; z++)
                        {
                            //The global scale of the subdivision
                            Vector3 scaleSubdivision = new Vector3(gameObj.transform.localScale.x / maxSubdivision.x,
                                                                   gameObj.transform.localScale.y / maxSubdivision.y,
                                                                   gameObj.transform.localScale.z / maxSubdivision.z);

                            //Local subdivision position, by going from Vector3(-0.5) to Vector3(0.5)
                            Vector3 positionSubdivision = positionOriginSubdivision + new Vector3((x / maxSubdivision.x), (y / maxSubdivision.y), (z / maxSubdivision.z));

                            //Instancing the mini object from the blood pool
                            GameObject miniObject = BloodManager.instance.GetPoolInstance();
                            miniObject.transform.position = positionSubdivision;
                            miniObject.transform.rotation = gameObj.transform.rotation;

                            //We set the local scale (which is the global scale)
                            miniObject.transform.localScale = scaleSubdivision;

                            //We set it under the parent object to conserve physic-links for the beginning
                            //This trick avoid us to do the maths of the correct translation, taking rotation into account
                            miniObject.transform.SetParent(gameObj.transform);
                            miniObject.transform.localPosition = positionSubdivision;

                            //If the object is "hidden" in the center of the cube subdivided
                            //Tag "SubdivideTop" : top of the cube, don't display bloody subdivision at the top
                            //Tag "SubdivideBottom" : bottom of the cube, don't display bloody subdivision at the bottom
                            if ((x > 0 && x < maxSubdivision.x - 1 && z > 0 && z < maxSubdivision.z - 1) &&
                                ((y > 0 || gameObj.CompareTag("SubdivideBottom") || gameObj.CompareTag("SubdivideInside")) &&
                                 (y < maxSubdivision.y - 1 || gameObj.CompareTag("SubdivideTop") || gameObj.CompareTag("SubdivideInside"))))
                            {
                                //The Cubes insides are blood
                                BloodManager.instance.registerNewBloodObject(miniObject.GetComponent <BloodObject>() ?? miniObject.AddComponent <BloodObject>());
                            }
                            else
                            {
                                //The cubes are body part, we change the material
                                miniObject.GetComponent <MeshRenderer>().sharedMaterial = gameObj.GetComponent <MeshRenderer>().sharedMaterial;
                                BloodManager.instance.registerNewBodyPartObject(miniObject.GetComponent <BloodObject>() ?? miniObject.AddComponent <BloodObject>());
                            }

                            instRigidObject.Add(miniObject.GetComponent <Rigidbody>());

                            subDivisionCount++;
                        }
                    }
                }

                //The layer of the parent must be in a layer that exclude the subdivisions, to avoid conflict during forces
                gameObj.layer = LayerMask.NameToLayer("AvoidMovables");

                //We enable all the physics. Note that it can be tweaked to have a better rag-doll reaction.
                boxObj.enabled       = true;
                rigidObj.useGravity  = true;
                rigidObj.isKinematic = false;
                rigidObj.mass        = 0.2f;
                rigidObj.drag        = 10f;
                rigidObj.angularDrag = 0f;

                //To move the parent object, we had a force relative to the bullet position and the bullet physical force
                rigidObj.AddForceAtPosition((bullet.transform.forward).normalized * bullet.physicalForceBullet, bullet.transform.position, ForceMode.Force);

                //We take the biggest part of the body to carry other tiny parts
                if (subDivisionCount > subDivisionMaxCount)
                {
                    parentObjectOfTinyBodyPart = gameObj;
                    subDivisionMaxCount        = subDivisionCount;
                }

                gameObj.GetComponent <MeshRenderer>().enabled = false;
                parentToDestroy.Add(gameObj);
            }
            else //If it's too small, we don't devide and use the object itself
            {
                BloodManager.instance.registerNewBodyPartObject(rigidObj.gameObject.AddComponent <BloodObject>());
                bodyPartRigidObject.Add(rigidObj);
            }
        }

        //If there's any parent of subdivision, we find the biggest one and assume that it's the body.
        if (parentObjectOfTinyBodyPart != null)
        {
            //We make children every body parts that are not subdivide
            foreach (Rigidbody rbo in bodyPartRigidObject)
            {
                rbo.transform.SetParent(parentObjectOfTinyBodyPart.transform);
            }
        }


        //We apply a force into all the small object, like a shockwave, closer the object is from the impact, higher will be the force.
        //Only the object in the shockwave moves. Others stays non-physics for the moment
        foreach (Rigidbody rbo in instRigidObject)
        {
            float rboDistance = Vector3.Distance(rbo.transform.position, bullet.transform.position);
            if (rboDistance < bullet.impactRadius)
            {
                InstanceManager.instance.MoveTo(InstanceManager.InstanceType.Graphics, rbo.gameObject);
                rbo.isKinematic = false;
                rbo.useGravity  = true;
                rbo.isKinematic = false;
                rbo.GetComponent <BoxCollider>().enabled = true;
                rbo.AddForce((rbo.transform.position - bullet.transform.position).normalized * bullet.forceImpactInRadius.Evaluate(rboDistance / bullet.impactRadius) * bullet.forceImpact, ForceMode.Impulse);
            }
        }
        instRigidObject.RemoveAll(c => c.useGravity);
        instRigidObject.AddRange(bodyPartRigidObject);

        //We enable physics after a shot period of time
        Invoke("EnableAllRigidbodyPhysics", timeBeforeDivideOnDeath);
    }
예제 #7
0
        public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult,
                                           Vector3 previousTorque, float maxTorque, float maxAoA, FloatCurve liftCurve, FloatCurve dragCurve)
        {
            Rigidbody rb         = ml.part.rb;
            double    airDensity = ml.vessel.atmDensity;
            double    airSpeed   = ml.vessel.srfSpeed;
            Vector3d  velocity   = ml.vessel.srf_velocity;

            //temp values
            Vector3 CoL            = new Vector3(0, 0, -1f);
            float   liftMultiplier = BDArmorySettings.GLOBAL_LIFT_MULTIPLIER;
            float   dragMultiplier = BDArmorySettings.GLOBAL_DRAG_MULTIPLIER;


            //lift
            float AoA = Mathf.Clamp(Vector3.Angle(ml.transform.forward, velocity.normalized), 0, 90);

            if (AoA > 0)
            {
                double  liftForce      = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * liftMultiplier * liftCurve.Evaluate(AoA);
                Vector3 forceDirection = Vector3.ProjectOnPlane(-velocity, ml.transform.forward).normalized;
                rb.AddForceAtPosition((float)liftForce * forceDirection,
                                      ml.transform.TransformPoint(ml.part.CoMOffset + CoL));
            }

            //drag
            if (airSpeed > 0)
            {
                double dragForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * dragMultiplier * dragCurve.Evaluate(AoA);
                rb.AddForceAtPosition((float)dragForce * -velocity.normalized,
                                      ml.transform.TransformPoint(ml.part.CoMOffset + CoL));
            }


            //guidance
            if (airSpeed > 1)
            {
                Vector3 targetDirection;
                float   targetAngle;
                if (AoA < maxAoA)
                {
                    targetDirection = (targetPosition - ml.transform.position);
                    targetAngle     = Vector3.Angle(velocity.normalized, targetDirection) * 4;
                }
                else
                {
                    targetDirection = velocity.normalized;
                    targetAngle     = AoA;
                }

                Vector3 torqueDirection = -Vector3.Cross(targetDirection, velocity.normalized).normalized;
                torqueDirection = ml.transform.InverseTransformDirection(torqueDirection);

                float   torque      = Mathf.Clamp(targetAngle * steerMult, 0, maxTorque);
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, torqueDirection * torque, 1),
                                                             Vector3.forward);

                rb.AddRelativeTorque(finalTorque);

                return(finalTorque);
            }
            else
            {
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, Vector3.zero, 0.25f),
                                                             Vector3.forward);
                rb.AddRelativeTorque(finalTorque);
                return(finalTorque);
            }
        }
예제 #8
0
    void FixedUpdate()
    {
        //  Do hover/bounce force
        RaycastHit hit;
        bool       onGround = false;

        for (int i = 0; i < hoverPoints.Length; i++)
        {
            var hoverPoint = hoverPoints[i];
            //lancer de rayons pour savoir si le véhicule est au sol
            if (Physics.Raycast(hoverPoint.transform.position, -Vector3.up, out hit, hoverHeight, layerMask))
            {
                //surélévation du véhicule afin d'éviter les frottement avec le sol
                body.AddForceAtPosition(Vector3.up * hoverForce * (0.9f - (hit.distance / hoverHeight)), hoverPoint.transform.position);
                onGround = true;
            }
            else
            {
                //si le véhicule n'est pas au sol on simule la gravité pour le faire descendre
                //stabilise également le véhicule si il se trouve de travers
                if (transform.position.y > hoverPoint.transform.position.y)
                {
                    body.AddForceAtPosition(hoverPoint.transform.up * gravityForce, hoverPoint.transform.position);
                }
                else
                {
                    body.AddForceAtPosition(hoverPoint.transform.up * -gravityForce, hoverPoint.transform.position);
                }
            }
        }

        //emission d'une trainée si le vehicule est au sol
        var emissionRate = 0;

        if (onGround)
        {
            body.drag    = groundedDrag;
            emissionRate = 10;
        }
        else
        {
            body.drag  = 0.1f;
            thrust    /= 100f;
            turnValue /= 100f;
        }


        // émettre une trainée derrière le véhicule
        if (dustTrails.Length > 0)
        {
            for (int i = 0; i < dustTrails.Length; i++)
            {
                var emission = dustTrails[i].emission;
            }
        }

        // faire avancer/reculer le vehicule
        if (Mathf.Abs(thrust) > 0)
        {
            body.AddForce(transform.forward * thrust);
        }

        // faire tourner le vehicule
        if (turnValue > 0)
        {
            body.AddRelativeTorque(Vector3.up * turnValue * turnStrength);
        }
        else if (turnValue < 0)
        {
            body.AddRelativeTorque(Vector3.up * turnValue * turnStrength);
        }

        if (body.velocity.sqrMagnitude > (body.velocity.normalized * maxVelocity).sqrMagnitude)
        {
            body.velocity = body.velocity.normalized * maxVelocity;
        }
    }
예제 #9
0
    // Update is called once per frame
    void Update()
    {
        if (!isGrounded && canDash && particulasJump.gameObject.activeSelf == false)
        {
            StartCoroutine(turnJumpParticlesOn());
        }
        if (!isGrounded && !canDash)
        {
            particulasJump.gameObject.SetActive(false);
        }
        //Registra la velocidad en X y Y del personaje
        lastFrameVelocity = rb.velocity;
        velY = rb.velocity.y;
        velX = rb.velocity.x;
        //Si el jugador esta moviendose mientras no esta en el aire, reproduce la animacion de Grund Dash
        if (Gdash)
        {
            knight_animation.SetBool("Gdash", true);
        }
        else
        {
            knight_animation.SetBool("Gdash", false);
        }
        //Regristra si el jugador esta moviendose para las animaciones
        speed = rb.velocity.magnitude;
        knight_animation.SetFloat("speed", (float)velX);

        if (alive)
        {
            if (Input.GetKeyDown(KeyCode.R))
            {
                saved_variables.progreso.score    = 0;
                saved_variables.progreso.hscore   = 0;
                saved_variables.progreso.Tutorial = true;
            }

            //Checks if player is touching the ground
            if (isGrounded)
            {
                //Apaga las particulas que indican si tienes un dash extra disponible
                transform.GetChild(5).gameObject.SetActive(false);
                //Indica que estoy haciendo un dash en el suelo
                if (velX > 0 && velY == 0)
                {
                    Gdash = true;
                }
                //Si el jugador "aterriza", hace que su velocidad sea 0 para que no derrape
                if (landing && velY <= 0)
                {
                    landing     = false;
                    rb.velocity = new Vector3(0, 0, 0);
                }
            }

            //Dash
            if (direction == 0 && dashTime == startDashTime && !p.paused)
            {
                //Testing with mouse
                if (Input.GetButtonDown("Fire1") && !p.paused)
                {
                    touchStart = Input.mousePosition;
                }
                if (Input.GetButtonUp("Fire1") && !p.paused)
                {
                    touchEnd    = Input.mousePosition;
                    direction   = 5;
                    stopDashing = false;
                    transform.GetChild(5).gameObject.SetActive(false);
                }
            }
            else
            {
                //Checks if dash is complete and if so, returns direction to 0. Allowing the player to dash again.
                if (dashTime <= 0.0f && !stopDashing)
                {
                    stopDashing = true;
                    dashTime    = startDashTime;
                    direction   = 0;
                }
                else
                {
                    if (!p.paused)
                    {
                        if (!stopDashing)
                        {
                            dashTime -= Time.deltaTime;
                        }
                        if (direction == 1)
                        {
                            rb.velocity = Vector3.left * dashSpeed;
                        }
                        else if (direction == 2)
                        {
                            rb.velocity = Vector3.right * dashSpeed;
                        }
                        else if (direction == 3)
                        {
                            canDash     = false;
                            rb.velocity = Vector3.up * dashSpeed;
                        }
                        else if (direction == 4)
                        {
                            rb.velocity = Vector3.down * dashSpeed;
                        }
                        else if (direction == 5)
                        {
                            DoInput();
                        }
                    }
                }
            }

            //Jump

            if (isGrounded && Input.GetKeyDown(KeyCode.Space) && !p.paused)
            {
                jump();
            }

            if (!isGrounded && Input.GetKeyDown(KeyCode.Space))
            {
                groundPound();
            }

            if (!isGrounded && direction == 0)
            {
                if (rb)
                {
                    rb.AddForceAtPosition(new Vector3(0f, fallMultiplier * -1, 0f), Vector3.down);
                }
            }
        }
    }
예제 #10
0
 // SuperCollision - Adds actual force for marble-marble collisions across the network.
 [RPC] public void SuperCollision(Vector3 velocity, Vector3 position)
 {
     //marbody.AddExplosionForce(velocity.magnitude * 5, position, 2, 0.25f, ForceMode.Impulse);
     marbody.AddForceAtPosition(velocity, position - (Vector3.up * 0.25f), ForceMode.Impulse);
 }
예제 #11
0
        void Break(LinkedShape shape, Vector3 point, Vector3 force, float quantitéDeMouvement, bool addVelocity)
        {
            if (linkedShapes.Count <= 1)
            {
                return;
            }

            if (intactVisual != null)
            {
                intactVisual.enabled = false;
            }

            //double time1 = EditorApplication.timeSinceStartup;
            Vector3 dir = force.normalized;

            float propagation = Mathf.Max(0, 0.025f * force.magnitude / (0.5f + elasticity) / massPerBlock);

            List <List <LinkedShape> > groups = shape.FormGroupsWithNeighbors(propagation, force.normalized, Mathf.Max(linkedShapes.Count / 2, 1), point);


            //Validate neighbors
            int totalInGroups = 0;

            for (int i = 0; i < groups.Count; i++)
            {
                totalInGroups += groups[i].Count;
                foreach (LinkedShape item in groups[i])
                {
                    item.ValidateNeighbors(groups[i]);
                }
            }
            int skipLastGroup = linkedShapes.Count > totalInGroups ? 0 : 1;

            //Remove groups from list
            for (int i = 0; i < groups.Count - skipLastGroup; i++)
            {
                List <LinkedShape> group = groups[i];
                foreach (LinkedShape item in group)
                {
                    linkedShapes.Remove(item);
                }
            }

            //Parcourt de l'arbre pour séparé les région qui ne sont plus en contact
            List <List <LinkedShape> > newGroups = FindSeperatedRegions();

            for (int i = 0; i < newGroups.Count; i++)
            {
                totalInGroups += newGroups[i].Count;
                foreach (LinkedShape item in newGroups[i])
                {
                    item.ValidateNeighbors(newGroups[i]);
                }
            }
            //Remove newGroups from list
            for (int i = 0; i < newGroups.Count; i++)
            {
                foreach (LinkedShape item in newGroups[i])
                {
                    linkedShapes.Remove(item);
                }
            }
            //Ajoute les nouveaux groupes à la liste
            groups.AddRange(newGroups);

            //Kinematic settings
            bool resetKinematic = false;

            if (myRb.isKinematic)
            {
                resetKinematic   = true;
                myRb.isKinematic = false;
            }
            Vector3 oldMassCenter = myRb.worldCenterOfMass;


            float velocityChange = quantitéDeMouvement / (totalInGroups * massPerBlock);

            //Nouveaux blocka
            for (int i = 0; i < groups.Count - skipLastGroup; i++)
            {
                List <LinkedShape> group   = groups[i];
                FragmentTree       newTree = Instantiate(newChunkPrefab.gameObject).GetComponent <FragmentTree>();
                newTree.linkedShapes   = group;
                newTree.hardness       = hardness;
                newTree.debugDraw      = debugDraw;
                newTree.relinkTree     = false;
                newTree.newChunkPrefab = newChunkPrefab;
                newTree.elasticity     = elasticity;
                newTree.original       = original;
                newTree.massPerBlock   = massPerBlock;

                Rigidbody rb = newTree.GetComponent <Rigidbody>();
                rb.velocity        = myRb.velocity;
                rb.angularVelocity = myRb.angularVelocity;
                rb.mass            = newTree.linkedShapes.Count * massPerBlock;
                rb.drag            = myRb.drag;
                rb.angularDrag     = myRb.angularDrag;
                rb.ResetCenterOfMass();

                foreach (LinkedShape item in group)
                {
                    item.shape.tr.SetParent(newTree.transform, true);
                }

                Vector3 dist      = rb.worldCenterOfMass - point;
                float   alignment = Vector3.Dot(dist.normalized, dir);                  //de 0 à 1
                                                                                        //float forceRatio = Mathf.Max(1.5f + 0.5f*alignment, 0.1f); // REMOVE
                float distanceFactor = Mathf.Pow(1 / (dist.magnitude + 1), elasticity); // de 0 à 1

                Vector3 addVel = dir * velocityChange * alignment * distanceFactor * 2;
                //print("remains: " + alignment * distanceFactor + "   vel: " + addVel);

                if (addVelocity)
                {
                    rb.AddForceAtPosition(addVel, point, ForceMode.VelocityChange);
                }
                //rb.AddExplosionForce(force.magnitude*forceRatio, point, 10, 0);
            }

            //Reset mass settings
            myRb.ResetCenterOfMass();
            myRb.mass = linkedShapes.Count * massPerBlock;

            if (resetKinematic)
            {
                Vector3 newCenterOfMass = myRb.worldCenterOfMass;

                if (oldMassCenter.y < newCenterOfMass.y)
                {
                    myRb.isKinematic = false;
                }
                else
                {
                    myRb.isKinematic = true;
                }
            }
        }
예제 #12
0
    //Add all forces that act on the squares below the water
    void AddUnderWaterForces()
    {
        //The resistance coefficient - same for all triangles
        float Cf = BoatPhysicsMath.ResistanceCoefficient(
            rhoWater,
            boatRB.velocity.magnitude,
            modifyBoatMesh.CalculateUnderWaterLength());

        //To calculate the slamming force we need the velocity at each of the original triangles
        List <SlammingForceData> slammingForceData = modifyBoatMesh.slammingForceData;

        CalculateSlammingVelocities(slammingForceData);

        //Need this data for slamming forces
        float boatArea = modifyBoatMesh.boatArea;
        float boatMass = boatRB.mass; //Replace this line with your boat's total mass

        //To connect the submerged triangles with the original triangles
        List <int> indexOfOriginalTriangle = modifyBoatMesh.indexOfOriginalTriangle;

        //Get all triangles
        List <TriangleData> underWaterTriangleData = modifyBoatMesh.underWaterTriangleData;

        for (int i = 0; i < underWaterTriangleData.Count; i++)
        {
            TriangleData triangleData = underWaterTriangleData[i];


            //Calculate the forces
            Vector3 forceToAdd = Vector3.zero;

            //Force 1 - The hydrostatic force (buoyancy)
            forceToAdd += BoatPhysicsMath.BuoyancyForce(rhoWater, triangleData);

            //Force 2 - Viscous Water Resistance
            forceToAdd += BoatPhysicsMath.ViscousWaterResistanceForce(rhoWater, triangleData, Cf);

            //Force 3 - Pressure drag
            forceToAdd += BoatPhysicsMath.PressureDragForce(triangleData);

            //Force 4 - Slamming force
            //Which of the original triangles is this triangle a part of
            int originalTriangleIndex = indexOfOriginalTriangle[i];

            SlammingForceData slammingData = slammingForceData[originalTriangleIndex];

            forceToAdd += BoatPhysicsMath.SlammingForce(slammingData, triangleData, boatArea, boatMass);


            //Add the forces to the boat
            boatRB.AddForceAtPosition(forceToAdd, triangleData.center);


            //Debug

            //SlammingForce
            //Debug.DrawRay (triangleData.center, BoatPhysicsMath.SlammingForce (slammingData, triangleData, boatArea, boatMass), Color.blue);

            //Normal
            //Debug.DrawRay(triangleData.center, triangleData.normal * 3f, Color.white);

            //Buoyancy
            //Debug.DrawRay(triangleData.center, BoatPhysicsMath.BuoyancyForce(rhoWater, triangleData).normalized * -3f, Color.red);

            //Velocity
            //Debug.DrawRay(triangleCenter, triangleVelocityDir * 3f, Color.black);

            //Viscous Water Resistance
            //Debug.DrawRay(triangleData.center, BoatPhysicsMath.ViscousWaterResistanceForce(rhoWater, triangleData, Cf).normalized * 0.3f, Color.black);
        }
    }
예제 #13
0
        /// <summary>
        /// The object has taken been damaged.
        /// </summary>
        /// <param name="amount">The amount of damage taken.</param>
        /// <param name="position">The position of the damage.</param>
        /// <param name="direction">The direction that the object took damage from.</param>
        /// <param name="forceMagnitude">The magnitude of the force that is applied to the object.</param>
        /// <param name="frames">The number of frames to add the force to.</param>
        /// <param name="radius">The radius of the explosive damage. If 0 then a non-explosive force will be used.</param>
        /// <param name="attacker">The GameObject that did the damage.</param>
        /// <param name="hitCollider">The Collider that was hit.</param>
        public virtual void OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, Collider hitCollider)
        {
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (m_NetworkInfo != null && m_NetworkInfo.IsServer())
            {
                m_NetworkHealthMonitor.OnDamage(amount, position, direction, forceMagnitude, frames, radius, attacker, hitCollider);
            }
#endif

            // Add a multiplier if a particular collider was hit. Do not apply a multiplier if the damage is applied through a radius because multiple
            // collider are hit.
            if (radius == 0 && direction != Vector3.zero && hitCollider != null)
            {
                Hitbox hitbox;
                if (m_ColliderHitboxMap != null && m_ColliderHitboxMap.Count > 0)
                {
                    if (m_ColliderHitboxMap.TryGetValue(hitCollider, out hitbox))
                    {
                        amount *= hitbox.DamageMultiplier;
                    }
                    else
                    {
                        // The main collider may be overlapping child hitbox colliders. Perform one more raycast to ensure a hitbox collider shouldn't be hit.
                        float distance = 0.2f;
                        if (hitCollider is CapsuleCollider)
                        {
                            distance = (hitCollider as CapsuleCollider).radius;
                        }
                        else if (hitCollider is SphereCollider)
                        {
                            distance = (hitCollider as SphereCollider).radius;
                        }

                        // The hitbox collider may be underneath the base collider. Fire a raycast to detemine if there are any colliders underneath the hit collider
                        // that should apply a multiplier.
                        var hitCount = Physics.RaycastNonAlloc(position, direction, m_RaycastHits, distance,
                                                               ~(1 << LayerManager.IgnoreRaycast | 1 << LayerManager.Overlay | 1 << LayerManager.VisualEffect), QueryTriggerInteraction.Ignore);
                        for (int i = 0; i < hitCount; ++i)
                        {
                            var closestRaycastHit = QuickSelect.SmallestK(m_RaycastHits, hitCount, i, m_RaycastHitComparer);
                            if (closestRaycastHit.collider == hitCollider)
                            {
                                continue;
                            }
                            // A new collider has been found - stop iterating if the hitbox map exists and use the hitbox multiplier.
                            if (m_ColliderHitboxMap.TryGetValue(closestRaycastHit.collider, out hitbox))
                            {
                                amount     *= hitbox.DamageMultiplier;
                                hitCollider = hitbox.Collider;
                                break;
                            }
                        }
                    }
                }
            }

            // Apply the damage to the shield first because the shield can regenrate.
            if (m_ShieldAttribute != null && m_ShieldAttribute.Value > m_ShieldAttribute.MinValue)
            {
                var shieldAmount = Mathf.Min(amount, m_ShieldAttribute.Value - m_ShieldAttribute.MinValue);
                amount -= shieldAmount;
                m_ShieldAttribute.Value -= shieldAmount;
            }

            // Decrement the health by remaining amount after the shield has taken damage.
            if (m_HealthAttribute != null && m_HealthAttribute.Value > m_HealthAttribute.MinValue)
            {
                m_HealthAttribute.Value -= Mathf.Min(amount, m_HealthAttribute.Value - m_HealthAttribute.MinValue);
            }

            var force = direction * forceMagnitude;
            if (forceMagnitude > 0)
            {
                // Apply a force to the object.
                if (m_ForceObject != null)
                {
                    m_ForceObject.AddForce(force, frames);
                }
                else
                {
                    // Apply a force to the rigidbody if the object isn't a character.
                    if (m_Rigidbody != null && !m_Rigidbody.isKinematic)
                    {
                        if (radius == 0)
                        {
                            m_Rigidbody.AddForceAtPosition(force * MathUtility.RigidbodyForceMultiplier, position);
                        }
                        else
                        {
                            m_Rigidbody.AddExplosionForce(force.magnitude * MathUtility.RigidbodyForceMultiplier, position, radius);
                        }
                    }
                }
            }

            // Let other interested objects know that the object took damage.
            EventHandler.ExecuteEvent <float, Vector3, Vector3, GameObject, Collider>(m_GameObject, "OnHealthDamage", amount, position, force, attacker, hitCollider);
            if (m_OnDamageEvent != null)
            {
                m_OnDamageEvent.Invoke(amount, position, force, attacker);
            }

            // The object is dead when there is no more health or shield.
            if (!IsAlive())
            {
                Die(position, force, attacker);
            }
            else
            {
                // Play any take damage audio if the object did not die. If the object died then the death audio will play.
                m_TakeDamageAudioClipSet.PlayAudioClip(m_GameObject);
            }
        }
예제 #14
0
        //todo anti roll when car is out of control
        void AntiRollBars()
        {

            //Horizontal anti roll

            float travelFL = 1f;
            float travelFR = 1f;

            //if front left wheel is grounded
            bool groundedFL = wheels[0].wheelCollider.GetGroundHit(out WheelHit wheelHit);
            if (groundedFL)
                travelFL = (-wheels[0].wheelTransform.InverseTransformPoint(wheelHit.point).y - wheels[0].wheelCollider.radius) / wheels[0].wheelCollider.suspensionDistance;

            //if front right wheel is grounded
            bool groundedFR = wheels[1].wheelCollider.GetGroundHit(out wheelHit);
            if (groundedFR)
                travelFR = (-wheels[1].wheelTransform.InverseTransformPoint(wheelHit.point).y - wheels[1].wheelCollider.radius) / wheels[1].wheelCollider.suspensionDistance;

            float antiRollFrontHorizontal = (travelFL - travelFR) * this.antiRollFrontHorizontal;

            //anti roll force
            if (groundedFL)
                rigidBody.AddForceAtPosition(wheels[0].wheelTransform.up * -antiRollFrontHorizontal, wheels[0].wheelTransform.position);
            if (groundedFR)
                rigidBody.AddForceAtPosition(wheels[1].wheelTransform.up * antiRollFrontHorizontal, wheels[1].wheelTransform.position);


            float travelRL = 1f;
            float travelRR = 1f;

            //if rear left wheel is grounded
            bool groundedRL = wheels[2].wheelCollider.GetGroundHit(out wheelHit);
            if (groundedRL)
                travelRL = (-wheels[2].wheelTransform.InverseTransformPoint(wheelHit.point).y - wheels[2].wheelCollider.radius) / wheels[2].wheelCollider.suspensionDistance;

            //if rear right wheel is grounded
            bool groundedRR = wheels[3].wheelCollider.GetGroundHit(out wheelHit);
            if (groundedRR)
                travelRR = (-wheels[3].wheelTransform.InverseTransformPoint(wheelHit.point).y - wheels[3].wheelCollider.radius) / wheels[3].wheelCollider.suspensionDistance;

            float antiRollRearHorizontal = (travelRL - travelRR) * this.antiRollRearHorizontal;

            //anti roll force
            if (groundedRL)
                rigidBody.AddForceAtPosition(wheels[2].wheelTransform.up * -antiRollRearHorizontal, wheels[2].wheelTransform.position);
            if (groundedRR)
                rigidBody.AddForceAtPosition(wheels[3].wheelTransform.up * antiRollRearHorizontal, wheels[3].wheelTransform.position);


            //Vertical anti roll

            float antiRollFrontVertical = (travelFL - travelRL) * antiRollVertical;

            if (groundedFL)
                rigidBody.AddForceAtPosition(wheels[0].wheelTransform.up * -antiRollFrontVertical, wheels[0].wheelTransform.position);
            if (groundedRL)
                rigidBody.AddForceAtPosition(wheels[2].wheelTransform.up * antiRollFrontVertical, wheels[2].wheelTransform.position);

            float antiRollRearVertical = (travelFR - travelRR) * antiRollVertical;

            if (groundedFR)
                rigidBody.AddForceAtPosition(wheels[1].wheelTransform.up * -antiRollRearVertical, wheels[1].wheelTransform.position);
            if (groundedRR)
                rigidBody.AddForceAtPosition(wheels[3].wheelTransform.up * antiRollRearVertical, wheels[3].wheelTransform.position);

        }
예제 #15
0
 public void AddForceAtPosition(Vector3 force, Vector3 position)
 {
     mRigidBody.AddForceAtPosition(force, position);
 }
예제 #16
0
    // Update is called once per frame
    void FixedUpdate()
    {
        //Input
        float throttleInput = Input.GetAxis("Throttle");
        float brakeInput    = Input.GetAxis("Brake");
        float steeringInput = Input.GetAxis("Steering");

        Vector3 velocity    = body.velocity;
        Vector3 angVelocity = body.angularVelocity;

        //Gearing
        if (Input.GetKeyDown(KeyCode.E) && currentGear < gearRatios.Length - 1)
        {
            currentGear++;
        }
        if (Input.GetKeyDown(KeyCode.Q) && currentGear > 0)
        {
            currentGear--;
        }

        if (gearbox == Gearbox.Automatic)
        {
            if (RPM >= maxRPM && currentGear < gearRatios.Length - 1)
            {
                currentGear++;
            }
            if (RPM <= 1500 && currentGear > 0)
            {
                currentGear--;
            }
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            transform.rotation = Quaternion.identity;
        }

        //Aero
        float   CDrag = (0.5f * 0.3f * frontArea * 1.29f);
        float   CRoll = 30 * CDrag;
        Vector3 FDrag = -CDrag * velocity * velocity.magnitude;
        Vector3 FRoll = -CRoll * velocity;

        //Braking
        float TBrake = brakePressure * brakeInput * -Mathf.Sign(speed);

        //Engine
        float avgAngularVelocity = 0;

        for (int i = 0; i < wheels.Length; i++)
        {
            avgAngularVelocity += wheels[i].angularVelocity;
        }
        avgAngularVelocity /= wheels.Length;


        RPM = (avgAngularVelocity * gearRatios[currentGear] * finalDriveRatio * 60) / (2 * Mathf.PI);
        if (RPM < 1000)
        {
            RPM = 1000;
        }
        if (RPM > maxRPM)
        {
            throttleInput = 0;
        }

        float TMax    = torqueCurve.Evaluate(RPM);
        float TEngine = 2 * TMax * throttleInput;
        float TDrive  = TEngine * gearRatios[currentGear] * finalDriveRatio * 0.7f;

        print(TDrive);

        //Apply
        for (int i = 0; i < wheels.Length; i++)
        {
            float FDrive = TDrive * wheels[i].radius;

            if (i < 2)
            {
                wheels[i].turnAngle = steeringInput * maxSteeringAngle;
            }
            else
            {
                body.AddForceAtPosition(transform.forward * FDrive, wheels[i].transform.position);
            }

            float wheelLongVelocity = Vector3.Dot(wheels[i].transform.forward, wheels[i].velocity / Time.fixedDeltaTime);
            float wheelLatVelocity  = Vector3.Dot(wheels[i].transform.right, wheels[i].velocity / Time.fixedDeltaTime);
            //print(wheels[i].gameObject.name + " | " + wheels[i].GetComponent<Rigidbody>().velocity);

            //Debug.DrawLine(transform.position, (wheels[i].velocity * 10) + transform.position, Color.blue);
            //Debug.DrawLine(wheels[i].transform.position, wheels[i].transform.position + (wheels[i].transform.right * 10), Color.red);
            body.AddForceAtPosition(-wheelLatVelocity * wheels[i].transform.right * 1000, wheels[i].transform.position);
            body.AddForceAtPosition(TBrake * wheels[i].transform.forward, wheels[i].transform.position);

            wheels[i].angularVelocity = Mathf.Rad2Deg * Vector3.Dot(wheels[i].transform.forward, wheels[i].velocity) * Mathf.PI;
        }

        speed = transform.InverseTransformVector(velocity).z * 3.6f;
    }
예제 #17
0
    void FixedUpdate()
    {
        if (OceanRenderer.Instance == null)
        {
            return;
        }

        UnityEngine.Profiling.Profiler.BeginSample("BoatAlignNormal.FixedUpdate");

        _sampleHeightHelper.Init(transform.position, _boatWidth, true);
        var height = OceanRenderer.Instance.SeaLevel;

        _sampleHeightHelper.Sample(out Vector3 disp, out var normal, out var waterSurfaceVel);

        // height = base sea level + surface displacement y
        height += disp.y;

        {
            _sampleFlowHelper.Init(transform.position, _boatWidth);

            _sampleFlowHelper.Sample(out var surfaceFlow);
            waterSurfaceVel += new Vector3(surfaceFlow.x, 0, surfaceFlow.y);
        }

        // I could filter the surface vel as the min of the last 2 frames. theres a hard case where a wavelength is turned on/off
        // which generates single frame vel spikes - because the surface legitimately moves very fast.

        if (_debugDraw)
        {
            Debug.DrawLine(transform.position + 5f * Vector3.up, transform.position + 5f * Vector3.up + waterSurfaceVel,
                           new Color(1, 1, 1, 0.6f));
        }

        var velocityRelativeToWater = _rb.velocity - waterSurfaceVel;

        float bottomDepth = height - transform.position.y - _bottomH;

        _inWater = bottomDepth > 0f;
        if (!_inWater)
        {
            UnityEngine.Profiling.Profiler.EndSample();
            return;
        }

        var buoyancy = -Physics.gravity.normalized * _buoyancyCoeff * bottomDepth * bottomDepth * bottomDepth;

        _rb.AddForce(buoyancy, ForceMode.Acceleration);

        // Approximate hydrodynamics of sliding along water
        if (_accelerateDownhill > 0f)
        {
            _rb.AddForce(new Vector3(normal.x, 0f, normal.z) * -Physics.gravity.y * _accelerateDownhill, ForceMode.Acceleration);
        }

        // apply drag relative to water
        var forcePosition = _rb.position + _forceHeightOffset * Vector3.up;

        _rb.AddForceAtPosition(Vector3.up * Vector3.Dot(Vector3.up, -velocityRelativeToWater) * _dragInWaterUp, forcePosition, ForceMode.Acceleration);
        _rb.AddForceAtPosition(transform.right * Vector3.Dot(transform.right, -velocityRelativeToWater) * _dragInWaterRight, forcePosition, ForceMode.Acceleration);
        _rb.AddForceAtPosition(transform.forward * Vector3.Dot(transform.forward, -velocityRelativeToWater) * _dragInWaterForward, forcePosition, ForceMode.Acceleration);

        float forward    = _throttleBias;
        float rawForward = Input.GetAxis("Vertical");

        if (_playerControlled)
        {
            forward += rawForward;
        }
        _rb.AddForceAtPosition(transform.forward * _enginePower * forward, forcePosition, ForceMode.Acceleration);

        float reverseMultiplier = (rawForward < 0f ? -1f : 1f);
        float sideways          = _steerBias;

        if (_playerControlled)
        {
            sideways +=
                (Input.GetKey(KeyCode.A) ? reverseMultiplier * -1f : 0f) +
                (Input.GetKey(KeyCode.D) ? reverseMultiplier * 1f : 0f);
        }
        _rb.AddTorque(transform.up * _turnPower * sideways, ForceMode.Acceleration);

        FixedUpdateOrientation(normal);

        UnityEngine.Profiling.Profiler.EndSample();
    }
예제 #18
0
    void HandleRaycast()
    {
        RaycastHit hit;

        int mask = (1 << LayerMask.NameToLayer("Track")) | (1 << LayerMask.NameToLayer("Default"));

        Camera cam = GetComponentInChildren <Camera>();

        foreach (Transform wheel in wheels)
        {
            onTrack = false;
            if (Physics.Raycast(wheel.position + transform.up * raycastStart, -transform.up, out hit, 50.0f, mask))
            {
                onTrack = true;
                if (enableGravity)
                {
                    float f = 10.0f;
                    if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Track"))
                    {
                        f = 50.0f;
                    }
                    rb.AddForceAtPosition(hit.normal * f * (hoverDist - hit.distance + raycastStart) * 0.25f, wheel.position, ForceMode.Acceleration);
                }


                if (Input.GetButton("Brake" + id))
                {
                    rb.drag = handBrakePower;
                }
                else
                {
                    rb.drag = drag;
                    rb.AddForce(transform.forward * Input.GetAxis("HLook" + id) * thrustPower * gc.playerSpeedMultiplier, ForceMode.Acceleration);
                    //rb.AddTorque(transform.up * Input.GetAxis("Horizontal"+id) * 1f, ForceMode.Acceleration);

                    float h = Vector3.Angle(transform.forward, cam.transform.forward) * 0.05f * Mathf.Abs(Input.GetAxis("HLook" + id));
                    if (h > 2)
                    {
                        h = 2;
                    }

                    rb.AddTorque(Vector3.Cross(transform.forward, cam.transform.forward).normalized *h, ForceMode.Acceleration);
                }
            }
        }

        if (Input.GetButton("Sudoku" + id))
        {
            if (cur_off_time < off_time)
            {
                cur_off_time += Time.deltaTime;
            }
            else
            {
                Die();
            }
        }
        else
        {
            cur_off_time = 0;
        }
    }
예제 #19
0
        public void Bang()
        {
            Vector3 position = (_useLocalPOI) ? _rigidbody.centerOfMass + _position : _position;

            _rigidbody.AddForceAtPosition(_force, position, _forceMode);
        }
예제 #20
0
    public void FixedUpdate()
    {
        //ResetInputs();

        //air drag (quadratic)
        rb.AddForce(-airDragCoeff * rb.velocity * rb.velocity.magnitude);

        //downforce (quadratic)
        rb.AddForce(-airDownForceCoeff * rb.velocity.sqrMagnitude * transform.up);

        //tire drag (Linear)
        rb.AddForceAtPosition(-tireDragCoeff * rb.velocity, transform.position);

        //calc current gear ratio
        float gearRatio = Mathf.Lerp(gearRatios[Mathf.FloorToInt(currentGear) - 1], gearRatios[Mathf.CeilToInt(currentGear) - 1], currentGear - Mathf.Floor(currentGear));

        if (InReverse)
        {
            gearRatio = -1.0f * gearRatios[0];
        }

        //calc engine RPM from wheel rpm
        float wheelsRPM = (axles[1].right.rpm + axles[1].left.rpm) / 2f;

        if (wheelsRPM < 0)
        {
            wheelsRPM = 0;
        }

        // if the engine is on, the fuel injectors are going to be triggered at minRPM
        // to keep the engine running.  If the engine is OFF, then the engine will eventually
        // go all the way down to 0, because there's nothing keeping it spinning.
        var minPossibleRPM = ignitionStatus == IgnitionStatus.On ? minRPM : 0.0f;

        currentRPM = Mathf.Lerp(currentRPM, minPossibleRPM + (wheelsRPM * finalDriveRatio * gearRatio), Time.fixedDeltaTime * RPMSmoothness);
        // I don't know why, but logging RPM while engine is off and we're not moving, is showing
        // a constant drift between 0.0185 and 0.0192 or so .. so just clamp it down to 0 at that
        // point.
        if (currentRPM < 0.02f)
        {
            currentRPM = 0.0f;
        }

        //find out which wheels are on the ground
        foreach (var axle in axles)
        {
            axle.isGroundedLeft  = axle.left.GetGroundHit(out axle.hitLeft);
            axle.isGroundedRight = axle.right.GetGroundHit(out axle.hitRight);
        }

        //convert inputs to torques
        float steer = maxSteeringAngle * steerInput;

        currentTorque = rpmCurve.Evaluate(currentRPM / maxRPM) * gearRatio * finalDriveRatio * tractionControlAdjustedMaxTorque;

        foreach (var axle in axles)
        {
            if (axle.steering)
            {
                axle.left.steerAngle  = steer;
                axle.right.steerAngle = steer;
            }
        }

        if (handbrakeApplied)
        {
            //Make the accellInput negative so that brakes are applied in ApplyTorque()
            accellInput = -1.0f;
        }

        // No autodrive while engine is off.
        if (ignitionStatus == IgnitionStatus.On)
        {
            AutoSteer();
        }

        ApplyTorque();
        TractionControl();

        //shift if need be. No auto shifting while engine is off.
        if (ignitionStatus == IgnitionStatus.On)
        {
            AutoGearBox();
        }

        //record current speed in MPH
        currentSpeed = rb.velocity.magnitude * 2.23693629f;

        float deltaDistance = wheelsRPM / 60.0f * (axles[1].left.radius * 2.0f * Mathf.PI) * Time.fixedDeltaTime;

        odometer += deltaDistance;

        /*
         * // why does this not work :(
         * float currentRPS = currentRPM / 60.0f;
         *
         * float accel = Mathf.Max(0.0f, accellInput);
         * float angularV = currentRPS * Mathf.PI * 2.0f;
         *
         * float power = currentTorque //(rpmCurve.Evaluate(currentRPM / maxRPM) * accel * maxMotorTorque)  //Nm
         * angularV; // Watt
         *
         * float energy = power * Time.fixedDeltaTime  // w/s
         *  / 1000.0f * 3600.0f;                    // kw/h
         *
         * print("p:" + power + " e:" + energy);
         * //approximation function for
         * // https://en.wikipedia.org/wiki/Brake_specific_fuel_consumption#/media/File:Brake_specific_fuel_consumption.svg
         * // range ~ 200-400 g/kWh
         * float bsfc = (206.0f + Mathf.Sqrt(Mathf.Pow(currentRPM - 2200, 2.0f)
         + Mathf.Pow((accel - 0.9f) * 10000.0f, 2.0f)) / 80 + currentRPM / 4500); // g/kWh
         +
         + float gasolineDensity = 1f / .75f;      // cm^3/g
         +
         + float deltaConsumption = bsfc * energy  // g
         * gasolineDensity                   // cm^3
         *  / 1000.0f;                          // l
         */

        // FIXME fix the more correct method above...
        float deltaConsumption = currentRPM * 0.00000001f
                                 + currentTorque * 0.000000001f * Mathf.Max(0.0f, accellInput);

        // if engine is not powered up, or there's zero acceleration, AND we're not idling
        // the engine to keep it on, then the fuel injectors are off, and no fuel is being used
        // idling == non-scientific calculation of "minRPM + 25%".
        if (ignitionStatus != IgnitionStatus.On || (accellInput <= 0.0f && currentRPM > minRPM + (minRPM * 0.25)))
        {
            deltaConsumption = 0.0f;
        }

        consumptionDistance = deltaConsumption / deltaDistance;       // l/m
        consumptionTime     = deltaConsumption / Time.fixedDeltaTime; // l/s

        fuelLevel -= deltaConsumption;

        float engineWeight     = 200.0f;                    // kg
        float energyDensity    = 34.2f * 1000.0f * 1000.0f; // J/l fuel
        float specificHeatIron = 448.0f;                    // J/kg for 1K temperature increase

        engineTemperatureK += (deltaConsumption * energyDensity) / (specificHeatIron * engineWeight);

        float coolFactor = 0.00002f; //ambient exchange

        if (engineTemperatureK > zeroK + 90.0f && !coolingMalfunction)
        {
            coolFactor += 0.00002f + 0.0001f * Mathf.Max(0.0f, currentSpeed); // working temperature reached, start cooling
        }
        engineTemperatureK = Mathf.Lerp(engineTemperatureK, ambientTemperatureK, coolFactor);

        //find current road surface type
        WheelHit hit;

        if (axles[0].left.GetGroundHit(out hit))
        {
            traction = hit.forwardSlip;
            var roadObject = hit.collider.transform.parent == null ? hit.collider.transform : hit.collider.transform.parent;
            CurrentSurface = roadType == "roads" || roadObject.CompareTag("Road") ? RoadSurface.Tarmac : RoadSurface.Offroad;
        }
        else
        {
            traction       = 0f;
            CurrentSurface = RoadSurface.Airborne;
        }

        //find traction values for audio
        tractionR  = axles[0].right.GetGroundHit(out hit) ? hit.forwardSlip : 0f;
        rtractionR = axles[1].right.GetGroundHit(out hit) ? hit.forwardSlip : 0f;
        rtraction  = axles[1].left.GetGroundHit(out hit) ? hit.forwardSlip : 0f;

        // apply turn signal logic
        const float turnSignalTriggerThreshold = 0.2f;
        const float turnSignalOffThreshold     = 0.1f;

        if (leftTurnSignal)
        {
            if (resetTurnSignal)
            {
                if (steerInput > -turnSignalOffThreshold)
                {
                    leftTurnSignal = false;
                }
            }
            else
            {
                if (steerInput < -turnSignalTriggerThreshold)
                {
                    // "click"
                    resetTurnSignal = true;
                }
            }
        }

        if (rightTurnSignal)
        {
            if (resetTurnSignal)
            {
                if (steerInput < turnSignalOffThreshold)
                {
                    rightTurnSignal = false;
                }
            }
            else
            {
                if (steerInput > turnSignalTriggerThreshold)
                {
                    // "click"
                    resetTurnSignal = true;
                }
            }
        }
    }
예제 #21
0
    void SuspensionForceAtWheel(Axle axle, WheelData wheelData)
    {
        Vector3 compressedWheelPos = WheelPosition(axle, wheelData, false);

        RaycastHit hit;

        int  layerMask    = canDriveOnEntities ? ~LayerMask.GetMask("Water") : LayerMask.GetMask("Terrain");
        bool hitSomething = Physics.Raycast(compressedWheelPos, -transform.up, out hit, axle.suspensionHeight, layerMask, QueryTriggerInteraction.Ignore);

        Debug.DrawLine(compressedWheelPos, compressedWheelPos - (transform.up * axle.suspensionHeight), Color.green);

        wheelData.isGrounded = hitSomething;


        if (hitSomething)
        {
            // calculate suspension force

            float suspensionLength   = hit.distance;
            float suspensionForceMag = 0.0f;

            wheelData.compression = 1.0f - Mathf.Clamp01(suspensionLength / axle.suspensionHeight);

            // Hooke's Law (springs)

            float springForce = wheelData.compression * -axle.suspensionStiffness;
            suspensionForceMag += springForce;

            // Damping force (try to rest velocity to 0)

            float suspensionCompressionVelocity = (wheelData.compression - wheelData.compressionPrev) / Time.deltaTime;
            wheelData.compressionPrev = wheelData.compression;

            float damperFoce = -suspensionCompressionVelocity * axle.suspensionDampining;
            suspensionForceMag += damperFoce;

            // Only consider component of force that is along contact normal

            float denom = Vector3.Dot(hit.normal, transform.up);
            suspensionForceMag *= denom;

            // Apply suspension force
            Vector3 suspensionForce = suspensionForceMag * -transform.up;
            rb.AddForceAtPosition(suspensionForce, hit.point);


            // calculate friction

            Vector3 wheelVelocity = rb.GetPointVelocity(hit.point);

            Vector3 contactUp      = hit.normal;
            Vector3 contactLeft    = -transform.right;
            Vector3 contactForward = transform.forward;

            // Calculate sliding velocity (without normal force)
            Vector3 lVel          = Vector3.Dot(wheelVelocity, contactLeft) * contactLeft;
            Vector3 fVel          = Vector3.Dot(wheelVelocity, contactForward) * contactForward;
            Vector3 slideVelocity = (lVel + fVel) * 0.5f;

            // Calculate current sliding force
            // (4 because we have 4 wheels)
            // TODO use num wheel variable
            Vector3 slidingForce = (slideVelocity * rb.mass / Time.deltaTime) / 4;

            float laterialFriciton = Mathf.Clamp01(axle.laterialFriction);

            Vector3 frictionForce = -slidingForce * laterialFriciton;

            Vector3 longitudinalForce = Vector3.Dot(frictionForce, contactForward) * contactForward;

            // TODO
            // Apply rolling-friction only if player doesn't press the accelerator
            float rollingK = 1.0f - Mathf.Clamp01(axle.rollingFriction);
            longitudinalForce *= rollingK;

            frictionForce -= longitudinalForce;

            rb.AddForceAtPosition(frictionForce, FixToCarCentre(hit.point));
        }
        else
        {
            // relax suspension
            wheelData.compressionPrev = wheelData.compression;
            wheelData.compression     = Mathf.Clamp01(wheelData.compression - axle.suspensionRelaxSpeed * Time.deltaTime);
        }
    }
        private IEnumerator AddGuideForce()
        {
            //if (blockRadar.target.transform != preTargetTransform)
            //{
            previousPosition = Vector3.zero;
            //preTargetTransform = blockRadar.target.transform;
            integral  = 0;
            lastError = 0;
            //}

            Vector3 addedForce;

            // Calculating the rotating axis
            Vector3 positionDiff = blockRadar.target.Position - parentBlock.transform.position;
            //Vector3 targetVelocity = blockRadar.target.rigidbody == null ?
            //    (blockRadar.target.Position - previousPosition) / Time.fixedDeltaTime : blockRadar.target.Velocity;
            Vector3 targetVelocity = blockRadar.target.Velocity;

            previousPosition = blockRadar.target.Position;
            Vector3 relVelocity = targetVelocity - parentBlock.Rigidbody.velocity;

            //float speed;
            bool turretMode;

            if (blockRadar.RadarType == RadarScript.RadarTypes.ActiveRadar)
            {
                turretMode = blockRadar.ShowBulletLanding;
                //speed = turretMode ? blockRadar.cannonBallSpeed : parentRigidbody.velocity.magnitude;
            }
            else
            {
                turretMode = blockRadar.passiveSourceRadar == null ? false : blockRadar.passiveSourceRadar.ShowBulletLanding && sourceSpeedPower < 0.1f;
                //speed = turretMode ? blockRadar.passiveSourceRadar.cannonBallSpeed : parentRigidbody.velocity.magnitude;
            }

            // Get the predicted point
            float   time;
            Vector3 positionDiffPredicted;

            if (turretMode)
            {
                Vector3 aimDir;
                if (blockRadar.RadarType == RadarScript.RadarTypes.ActiveRadar)
                {
                    aimDir = blockRadar.aimDir;
                }
                else
                {
                    aimDir = blockRadar.passiveSourceRadar == null ? Vector3.zero : blockRadar.passiveSourceRadar.aimDir;
                }
                positionDiffPredicted = parentBlock.transform.position + aimDir * parentBlock.transform.position.magnitude * 10000;
            }
            else
            {
                time = InterceptionCalculation.FirstOrderInterceptTime(parentRigidbody.velocity.magnitude, positionDiff, relVelocity);
                positionDiffPredicted = positionDiff + relVelocity * time;
            }
            positionDiffPredicted = positionDiffPredicted.normalized;

            // Get the angle difference
            float   dotProduct          = Vector3.Dot(ForwardDirection, positionDiffPredicted);
            Vector3 towardsPositionDiff = (dotProduct * positionDiffPredicted - ForwardDirection) * Mathf.Sign(dotProduct);

            towardsPositionDiff = towardsPositionDiff.normalized;

            if (constantForce)
            {
                addedForce = torque * maxTorque * towardsPositionDiff * 2000f;
            }
            else
            {
                float angleDiff = Vector3.Angle(ForwardDirection, positionDiff) + Vector3.Angle(positionDiff, positionDiffPredicted);
                integral += angleDiff * Time.fixedDeltaTime;
                float derivitive = (angleDiff - lastError) / Time.fixedDeltaTime;
                lastError = angleDiff;
                float coefficient = angleDiff * pFactor + integral * iFactor + derivitive * dFactor;
                addedForce = torque * maxTorque * coefficient * towardsPositionDiff;
            }

            // Add force to rotate rocket
            parentRigidbody.AddForceAtPosition(addedForce, parentBlock.transform.position + ForwardDirection);
            parentRigidbody.AddForceAtPosition(-addedForce, parentBlock.transform.position - ForwardDirection);
            yield break;
        }
예제 #23
0
    IEnumerator StartAction()
    {
        Debug.Log("Starting recording... waiting on Delay.");

        yield return(new WaitForSeconds(startSecondDelay));

        Debug.Log("Delay is over. Applying force.");

        switch (type)
        {
        case ForceType.Explosion:
            if (isOffSetRelative)
            {
                rb.AddExplosionForce(strength, transform.position + offSet, radius);
            }
            else
            {
                rb.AddExplosionForce(strength, offSet, radius);
            }
            break;

        case ForceType.Force:
            rb.AddForce(offSet * strength);
            //Maybe use a different Vector3
            //Add more options
            break;

        case ForceType.ForceAtPosition:
            if (isOffSetRelative)
            {
                rb.AddForceAtPosition(direction * strength, transform.position + offSet);
            }
            else
            {
                rb.AddForceAtPosition(direction * strength, offSet);
            }
            break;
        }

        Debug.Log("Setting up vars for recording...");

        isRecording      = true;                    //Set the status to being recorded
        currentTime      = 0;                       //Start at frame 0
        recordTimeFrames = (int)recordTime * 60;    //Convert to frames

        clip.ClearCurves();                         //Clear whatever was in this animtion before
        clip.legacy = false;                        //Set it to legacy so this method will work

        //Create enough keyframes for ourselves
        xPosKeys = new Keyframe[recordTimeFrames / recordingResolution];
        yPosKeys = new Keyframe[recordTimeFrames / recordingResolution];
        zPosKeys = new Keyframe[recordTimeFrames / recordingResolution];
        xRotKeys = new Keyframe[recordTimeFrames / recordingResolution];
        yRotKeys = new Keyframe[recordTimeFrames / recordingResolution];
        zRotKeys = new Keyframe[recordTimeFrames / recordingResolution];
        wRotKeys = new Keyframe[recordTimeFrames / recordingResolution];

        KeyPosRot();

        Debug.Log("Setup done. Initial keys set. Recording beginning...");
    }
예제 #24
0
 void AddForceAtPosition(Vector3 force, Vector3 position)
 {
     rb.AddForceAtPosition(force, position);
     // Debug.DrawRay(position, force, Color.magenta);
 }
예제 #25
0
    void RepelPlayer(Rigidbody player)
    {
        Vector3 repelVector = -(transform.position - player.transform.position).normalized * m_repelForce;

        player.AddForceAtPosition(repelVector, player.transform.position);
    }
예제 #26
0
    private void ApplyNeutralBuoyancy()
    {
        _buoyancyVector = -_relativeDownVector *_gravity *Random.Range(.99f, 1.01f) * thrustAmpFactor;

        _rigidbody.AddForceAtPosition(_buoyancyVector, _transform.TransformPoint(relativePosition), ForceMode.Acceleration);
    }
예제 #27
0
        private void FixedUpdateRotatorTrack()
        {
            var rotateForce = trackPoint.position - originalControllerAttachPoint.position;

            rb.AddForceAtPosition(rotateForce, originalControllerAttachPoint.position, ForceMode.VelocityChange);
        }
예제 #28
0
    public void FallDownByButtonPush()
    {
        Vector3 Extents = gameObject.GetComponent <Collider>().bounds.extents;

        rb.AddForceAtPosition(100 * transform.forward.normalized, transform.position + 0.8f * Extents);
    }
예제 #29
0
 public void EnableRagdoll(Rigidbody body, Vector3 point, Vector3 impulse)
 {
     EnableRagdoll();
     body?.AddForceAtPosition(impulse, point, ForceMode.Impulse);
 }
예제 #30
0
    /*
     *
     * // DEBUG
     *
     * private var m_lastVelocity = Vector3.zero;
     * private var m_velocity = Vector3.zero;
     * private var m_acceleration = Vector3.zero;
     * private var m_loadMass = 0.0;
     * private var m_force = Vector3.zero;
     *
     * static function Lin2Log(value : float) : float
     *      {
     *      return Mathf.Log(Mathf.Abs(value)+1) * Mathf.Sign(value);
     *      }
     *
     * static function Lin2Log(value : Vector3) : Vector3
     *      {
     *      return Vector3.ClampMagnitude(value, Lin2Log(value.magnitude));
     *      }
     *
     *
     * function Update ()
     *      {
     *      var hit : RaycastHit;
     *
     *      if (Physics.Raycast(m_wheel.transform.position, -m_wheel.transform.up, hit, (m_wheel.suspensionDistance + m_wheel.radius) * m_wheel.transform.lossyScale.y))
     *              {
     *              Debug.DrawLine(hit.point, hit.point + m_velocity * 1, Color.gray);
     *              Debug.DrawLine(hit.point, hit.point + m_acceleration * 1, Color.yellow);
     *              Debug.DrawLine(hit.point, hit.point + Lin2Log(m_force) * 0.1, Color.magenta);
     *              }
     *      }
     */


    void FixedUpdate()
    {
        /*
         * // DATOS Debug
         *
         * m_grounded = m_wheel.GetGroundHit(m_wheelHit);
         * if (m_grounded)
         *      {
         *      m_velocity = m_rigidbody.GetPointVelocity(m_wheelHit.point);
         *      m_acceleration = (m_velocity - m_lastVelocity) / Time.deltaTime;
         *      m_lastVelocity = m_velocity;
         *      m_loadMass = m_wheelHit.force / -Physics.gravity.y;
         *      m_force = m_acceleration * m_loadMass;
         *      }
         * else
         *      {
         *      m_velocity = Vector3.zero;
         *      m_lastVelocity = Vector3.zero;
         *      m_acceleration = Vector3.zero;
         *      m_loadMass = 0.0;
         *      m_force = Vector3.zero;
         *      }
         *
         * //-----------
         */

        // Calcular el ajuste temporal

        m_DeltaTimeFactor = Time.fixedDeltaTime * Time.fixedDeltaTime * 2500.0f;           // equivale a (fixedDeltaTime/0.02)^2

        // Determinar el estado de la rueda

        m_grounded = m_wheel.GetGroundHit(out m_wheelHit);

        // Calcular los elementos costosos (picos de las curvas de fricción)

        if (!optimized)
        {
            RecalculateStuff();
        }

        //======================================================================
        // 1. Fricción longitudinal
        //======================================================================

        // Calcular el rendimiento neto aceleración-freno aplicado sobre la rueda. Determinará el factor de amplificación (slopeFactor) a aplicar.

        float resultInput = Mathf.Abs(motorInput) - brakeInput;

        // Calcular parámetros de ajuste de la curva:
        // - fslipFactor escalará la curva de forma que el punto de máximo rendimiento coincida (mas o menos) con el valor dado.
        // - fSlopeFactor es el stiffnes que multiplicará a grip y a drift.
        //   Si es != 1.0 se desplaza ligeramente el punto de máximo rendimiento, pero no se nota mucho.

        float fSlipFactor  = serviceMode ? 1.0f : performancePeak / m_forwardFrictionPeak.y;
        float fSlopeFactor = resultInput >= 0 ? motorForceFactor : brakeForceFactor;

        // Calcular la curva correcta para el WheelCollider

        m_wheel.forwardFriction = GetWheelFrictionCurve(ForwardWheelFriction, fSlopeFactor, fSlipFactor);
        m_wheel.motorTorque     = SlipToTorque(motorInput);
        m_wheel.brakeTorque     = SlipToTorque(brakeInput);

        //======================================================================
        // 2. Fricción lateral
        //======================================================================

        // Calcular la pérdida de agarre lateral en función del rendimiento longitudinal de la rueda
        // Si la rueda está en el suelo se usa el slip longitundinal real, si no se usa el de la entrada.

        m_driftFactor = Mathf.Lerp(1.0f, sidewaysDriftFriction, Mathf.InverseLerp(m_wheel.forwardFriction.extremumSlip * m_forwardFrictionPeak.x, m_wheel.forwardFriction.asymptoteSlip, Mathf.Abs(m_grounded ? m_wheelHit.forwardSlip : resultInput)));

        // Calcular y aplicar la curva de fricción lateral en el WheelCollider

        fSlopeFactor             = serviceMode ? 1.0f : m_driftFactor * sidewaysForceFactor;
        m_wheel.sidewaysFriction = GetWheelFrictionCurve(SidewaysWheelFriction, fSlopeFactor, 1.0f);

        //======================================================================
        // 3. Datos, ajustes & correcciones
        //======================================================================

        if (m_grounded)
        {
            // Datos para telemetría

            WheelFrictionCurve sF = m_wheel.sidewaysFriction;
            WheelFrictionCurve fF = m_wheel.forwardFriction;

            m_forwardSlipRatio  = GetWheelSlipRatio(m_wheelHit.forwardSlip, fF.extremumSlip * m_forwardFrictionPeak.x, fF.asymptoteSlip);
            m_sidewaysSlipRatio = GetWheelSlipRatio(m_wheelHit.sidewaysSlip, sF.extremumSlip * m_sidewaysFrictionPeak.x, sF.asymptoteSlip);

            // Corregir el diseño de las curvas de fricción de WheelFrictionCurve
            // - Fricción lateral

            float absSlip = Mathf.Abs(m_wheelHit.sidewaysSlip);
            if (staticFrictionMax > sF.extremumValue && absSlip < sF.extremumSlip)                 // Baja velocidad - reforzar ligeramente el control estático del WheelCollider

            {
                sF.extremumValue = GetFixedSlope(CarWheelFriction.MCsideways, absSlip, sF.extremumSlip, sF.extremumValue, 0);
                if (sF.extremumValue > staticFrictionMax)
                {
                    sF.extremumValue = staticFrictionMax;
                }
            }

            if (absSlip > sF.asymptoteSlip)
            {
                sF.asymptoteValue = GetFixedSlope(CarWheelFriction.MCsideways, absSlip, sF.asymptoteSlip, sF.asymptoteValue, SidewaysWheelFriction.driftSlope);
            }

            // - Fricción longitudinal

            absSlip = Mathf.Abs(m_wheelHit.forwardSlip);
            if (absSlip > fF.asymptoteSlip)
            {
                fF.asymptoteValue = GetFixedSlope(CarWheelFriction.MCforward, absSlip, fF.asymptoteSlip, fF.asymptoteValue, ForwardWheelFriction.driftSlope);
            }

            // Ajustar la curva en función del terreno

            if (m_wheelHit.collider.sharedMaterial)
            {
                fF.stiffness *= (m_wheelHit.collider.sharedMaterial.dynamicFriction + 1.0f) * 0.5f;
                sF.stiffness *= (m_wheelHit.collider.sharedMaterial.dynamicFriction + 1.0f) * 0.5f;

                // Aplicar fuerza de resistencia fuera de la carretera

                Vector3 wheelV = m_rigidbody.GetPointVelocity(m_wheelHit.point);
                m_rigidbody.AddForceAtPosition(wheelV * wheelV.magnitude * -m_wheelHit.force * m_wheelHit.collider.sharedMaterial.dynamicFriction * 0.001f, m_wheelHit.point);
            }

            m_wheel.sidewaysFriction = sF;
            m_wheel.forwardFriction  = fF;
        }
        else
        {
            m_forwardSlipRatio  = 0;
            m_sidewaysSlipRatio = 0;
        }
    }