示例#1
0
        void ApplyFrictionForce(CustomRigidbody objectA, CustomRigidbody objectB, Vector2 normal, float impValue, Vector2 impulse)
        {
            //assign new friction values
            float aInverseMass = 1 / objectA.m_Mass;
            float bInverseMass = 1 / objectB.m_Mass;

            // Get the recalculated relative velocity after the previous impulse has been applied
            Vector2 rv = objectB.m_Velocity - objectA.m_Velocity;

            // Retrieve the tangent vector, the vector that determines the direction of friction force to apply
            Vector2 tangent = rv - Vector2.Dot(rv, normal) * normal;

            tangent.Normalize();

            // calculate the friction impulse value
            float jT = -Vector2.Dot(rv, tangent) / (aInverseMass + bInverseMass);

            // Coulombs law: force of friction <= force along the normal * mu
            float mu = (objectA.m_MaterialType.m_StaticFriction + objectB.m_MaterialType.m_StaticFriction) / 2;

            Vector2 frictionImpulse;

            // clamp the magnitude of the friction and create the friction impulse vector
            if (Mathf.Abs(jT) < impValue * mu)
            {
                frictionImpulse = jT * tangent;
            }
            else
            {
                float dynamicFriction = (objectA.m_MaterialType.m_DynamicFriction + objectB.m_MaterialType.m_DynamicFriction) / 2;
                impulse.Scale(tangent);
                Vector2 j = new Vector2(-impulse.x, -impulse.y);
                frictionImpulse = j * dynamicFriction;
            }

            objectA.m_Velocity -= (aInverseMass) * frictionImpulse;
            objectB.m_Velocity += (bInverseMass) * frictionImpulse;
        }
示例#2
0
        // all physics calculations are done within here
        // this is called from within MainManager
        public void PhysicsUpdate()
        {
            accum += deltaTime;

            //Calculate physics on the current frame
            while (accum > deltaTime)
            {
                colliderTest1        = null;
                colliderTest2        = null;
                currentCollisionPair = new List <CollisionPair>();
                depthX     = 0f;
                depthY     = 0f;
                xDistance  = 0f;
                yDistance  = 0f;
                xDirection = 0f;
                yDirection = 0f;

                // if no path simulate normally
                //calculate rigidbodies
                for (int i = 0; i < rigidBodiesInScene.Count; i++)
                {
                    // entity calc
                    if (rigidBodiesInScene[i].tag == "Entity")
                    {
                        bool charging = false;
                        recentHit = false;

                        // check if player attacked
                        // player charge attack
                        if (Input.GetMouseButtonDown(0))
                        {
                            chargeDmg  = 0;
                            chargeRate = 1000f;
                            charging   = true;

                            if (charging == true)
                            {
                                chargeDmg += chargeRate * Time.deltaTime;
                            }
                        }
                        if (Input.GetMouseButtonUp(0))
                        {
                            charging  = false;
                            chargeDmg = Mathf.Clamp(chargeDmg, 0f, 100f);
                            //create a player attack area and check if the enemy is inside it
                            GameObject   t       = Instantiate(Resources.Load("EntityAttack")) as GameObject;
                            GameObject   graphic = Instantiate(Resources.Load("AttackGraphic")) as GameObject;
                            EntityAttack et      = t.GetComponent <EntityAttack>();
                            et.InitAttack();
                            CustomRigidbody player = GameObject.FindGameObjectWithTag("Player").GetComponent <CustomRigidbody>();

                            Vector2 direction = et.GetDirection(player).normalized;
                            t.transform.position = (Vector2)player.transform.position + direction;

                            graphic.transform.position = (Vector2)player.transform.position + direction;
                            graphic.transform.SetParent(player.transform);

                            Transform[] q = graphic.GetComponentsInChildren <Transform>();

                            foreach (Transform tr in q)
                            {
                                if (tr.tag == "pointer")
                                {
                                    graphic.transform.rotation = tr.rotation;
                                }
                            }


                            if (et.IsColliding(rigidBodiesInScene[i]))
                            {
                                // if hit, set enemy velocity to the direction of where the player pointed
                                rigidBodiesInScene[i].m_IsIgnoringGravity = false;
                                rigidBodiesInScene[i].m_Velocity          = direction * chargeDmg;
                                rigidBodiesInScene[i].m_IsEnemyDead       = true;
                                Destroy(et.gameObject);
                                DestroyObject(graphic.gameObject, 0.5f);
                            }
                            else
                            {
                                DestroyObject(graphic.gameObject);
                                Destroy(et.gameObject, 0.5f);
                            }
                        }

                        // if entity has been attacked, dont path find
                        AStarPathfind a = new AStarPathfind();
                        if (rigidBodiesInScene[i].m_IsEnemyDead != true)
                        {
                            // calculate entity positions for pathfinding
                            playerPos = new Vector2(0, 0);
                            enemyPos  = new Vector2(0, 0);

                            for (int l = 0; l < entityBoundingBoxes.Count; l++)
                            {
                                if (entityBoundingBoxes[l].tag == "Player")
                                {
                                    playerPos = entityBoundingBoxes[l].transform.position;
                                }
                            }
                            // generate path to player
                            playerNode = grid.NodeFromWorldPoint(playerPos);
                            enemyNode  = grid.NodeFromWorldPoint(rigidBodiesInScene[i].transform.position);

                            path  = a.AStarSearch(grid, enemyNode, playerNode);
                            dPath = path;
                            //path = null;
                        }
                        else
                        {
                            Destroy(a);
                            path = null;
                        }

                        // if path exists move through it
                        if (path != null)
                        {
                            for (int j = 0; j < path.Count; j++)
                            {
                                rigidBodiesInScene[i].m_EnemyHasPath = false;
                                Vector2 direction = (path[j] - (Vector2)rigidBodiesInScene[i].transform.position);
                                direction.Normalize();
                                rigidBodiesInScene[i].m_EnemyMoveDirection = direction;
                                rigidBodiesInScene[i].m_EnemyHasPath       = true;
                                rigidBodiesInScene[i].EnemyPhysicsLoop();
                            }
                        }
                        // if entity has been attacked, re enable gravity
                        else if (path == null || rigidBodiesInScene[i].m_IsEnemyDead == true)
                        {
                            rigidBodiesInScene[i].m_EnemyHasPath      = false;
                            rigidBodiesInScene[i].m_IsIgnoringGravity = false;
                            rigidBodiesInScene[i].EnemyPhysicsLoop();
                        }
                    }
                    // calc player and other rigidbodies
                    if (rigidBodiesInScene[i].tag == "Player")
                    {
                        rigidBodiesInScene[i].PlayerPhysicsLoop();
                    }
                    else if (rigidBodiesInScene[i].tag != "Player" || rigidBodiesInScene[i].tag != "Entity")
                    {
                        rigidBodiesInScene[i].PlayerPhysicsLoop();
                    }
                }

                //calculate collisions
                for (int j = 0; j < entityBoundingBoxes.Count; j++)
                {
                    // this is the current entity we are checking colliders against
                    // we dont need to check collisions between platforms.
                    colliderTest1 = entityBoundingBoxes[j];

                    //collision between entity and ground
                    for (int k = 0; k < floorBoundingBoxes.Count; k++)
                    {
                        colliderTest2 = floorBoundingBoxes[k];

                        if (TestAABBOverlap(colliderTest1, colliderTest2))
                        {
                            if (colliderTest1.GetComponent <CustomRigidbody>().m_IsEnemyDead == true)
                            {
                                entityBoundingBoxes.Remove(colliderTest1);
                                rigidBodiesInScene.Remove(colliderTest1.GetComponent <CustomRigidbody>());
                                Destroy(colliderTest1.gameObject);
                                isEnemyActive = false;
                            }
                            colliderTest1.GetComponent <CustomRigidbody>().m_IsGrounded = true;
                            //Debug.Log(string.Format("Ground Collision between: {0} and {1}", colliderTest1, colliderTest2));
                            PopulateCollisionData(colliderTest1, colliderTest2);
                        }
                    }

                    //collision between entity and entity
                    for (int l = 0; l < entityBoundingBoxes.Count; l++)
                    {
                        colliderTest2 = entityBoundingBoxes[l];

                        //Don't collide with itself
                        if (colliderTest1 == colliderTest2)
                        {
                            continue;
                        }

                        if (TestAABBOverlap(colliderTest1, colliderTest2))
                        {
                            //Debug.Log(string.Format("Entity Collision between: {0} and {1}", colliderTest1, colliderTest2));
                            PopulateCollisionData(colliderTest1, colliderTest2);

                            float[] moveVals = { 12, -12 };

                            int chooseAxis = 0;
                            // enemy 'attacks'
                            // choose a random direction to set the players velocity in
                            if (colliderTest1.tag == "Player")
                            {
                                CustomRigidbody rb = colliderTest1.GetComponent <CustomRigidbody>();
                                rb.m_PlayerHasBeenHit = true;
                                float v = Random.Range(0, moveVals.Length);
                                chooseAxis = Random.Range(0, 1);
                                if (chooseAxis == 0)
                                {
                                    rb.m_Velocity = new Vector2(moveVals[Random.Range(0, moveVals.Length)], 0);
                                }
                                if (chooseAxis == 1)
                                {
                                    rb.m_Velocity = new Vector2(0, moveVals[Random.Range(0, moveVals.Length)]);
                                }
                            }
                            if (colliderTest2.tag == "Player")
                            {
                                CustomRigidbody rb = colliderTest2.GetComponent <CustomRigidbody>();
                                rb.m_PlayerHasBeenHit = true;
                                int v = Random.Range(0, moveVals.Length);
                                chooseAxis = Random.Range(0, 1);
                                if (chooseAxis == 0)
                                {
                                    rb.m_Velocity = new Vector2(moveVals[Random.Range(0, moveVals.Length)], 0);
                                }
                                if (chooseAxis == 1)
                                {
                                    rb.m_Velocity = new Vector2(0, moveVals[Random.Range(0, moveVals.Length)]);
                                }
                            }
                        }
                    }

                    // Finally check whether an entity has hit the boundaries of the screen
                    // and needs to be removed from scene
                    for (int i = 0; i < boundaryBoundingBoxes.Count; i++)
                    {
                        colliderTest2 = boundaryBoundingBoxes[i];

                        if (TestAABBOverlap(colliderTest1, colliderTest2))
                        {
                            if (colliderTest1.tag == "Player")
                            {
                                entityBoundingBoxes.Remove(colliderTest1);
                                rigidBodiesInScene.Remove(colliderTest1.GetComponent <CustomRigidbody>());
                                Destroy(colliderTest1.gameObject);
                                isPlayerActive = false;
                            }
                            if (colliderTest1.tag == "Entity")
                            {
                                entityBoundingBoxes.Remove(colliderTest1);
                                rigidBodiesInScene.Remove(colliderTest1.GetComponent <CustomRigidbody>());
                                Destroy(colliderTest1.gameObject);
                                isEnemyActive = false;
                            }
                        }
                    }
                }


                accum -= deltaTime;
            }
        }
示例#3
0
        void ResolveCollisionPair(List <CollisionPair> pairs)
        {
            CustomRigidbody objectA = pairs[0].m_ObjectA.GetComponent <CustomRigidbody>();
            CustomRigidbody objectB = pairs[0].m_ObjectB.GetComponent <CustomRigidbody>();

            // get relative velocity of each object this is used to find out how far to move each object
            Vector2 objAVelocity = objectA.m_Velocity;
            Vector2 objBVelocity = objectB.m_Velocity;

            Vector2 relativeVelocity = objBVelocity - objAVelocity;

            // normalise the contact normal to make sure it only points in the right direction
            Vector2 normalMagnitude = pairs[0].m_CollisionNormal;

            normalMagnitude.Normalize();

            // get the velocity along the normal
            float velocityAlongNormal = Vector2.Dot(relativeVelocity, normalMagnitude);

            // calculate the restitution (elasticity) which is between 0 and 1
            // should change to a property of each rigidbody
            float coefficientOfRestitution = Mathf.Min(0.01f, 0.02f);

            // calculate the inverse mass to impulse (force) the objects away
            // do this to save from having to calculate it like 5 more times
            float aInverseMass;
            float bInverseMass;

            if (objectA.m_Mass == 0)
            {
                aInverseMass = 0;
            }
            else
            {
                aInverseMass = 1 / objectA.m_Mass;
            }
            if (objectB.m_Mass == 0)
            {
                bInverseMass = 0;
            }
            else
            {
                bInverseMass = 1 / objectB.m_Mass;
            }

            // calculate the impulse
            float impulse = -(1 + coefficientOfRestitution) * velocityAlongNormal / (aInverseMass + bInverseMass);

            // create and assign the new velocities
            Vector2 imp = impulse * normalMagnitude;

            objectA.m_Velocity -= aInverseMass * imp;
            objectB.m_Velocity += bInverseMass * imp;


            // stop sinking objects by offsetting the positions to above a certain threshold
            // depending on the penetration depth

            float percent = 0.2f;           // the amount we want to move each colliding object
            float slop    = 0.01f;          // the amount we let the 2 objects sink into eachother to stop jittering
            float xAmount = 0f;
            float yAmount = 0f;

            // get the side that is being most penetrated
            xAmount = pairs[0].m_PenetrationDepth.x;
            yAmount = pairs[0].m_PenetrationDepth.y;

            Vector2 correction = Mathf.Max(-yAmount - slop, 0.0f) / (aInverseMass + bInverseMass) * percent * pairs[0].m_CollisionNormal;


            objectA.m_Velocity -= aInverseMass * correction;
            objectB.m_Velocity += bInverseMass * correction;
        }