Checking for collisions

So far, the player can throw the ball at the monster, with little effect. If you managed to hit the monster in your testing, you likely noticed the ball just bounces off, which is certainly not the result we are looking for. What we need now is a way of detecting when the ball hits the monster, or the plane for that matter. Fortunately, the Unity physics engine has a couple of methods to determine when an object collides with another object. Here are the standard options:

  • OnCollisionEnter: The object has a collider, which makes contact with another game object that also has a collider. The objects will make contact and then push away from each other depending on the force of the collision, and if either or both objects have a rigidbody attached. An object does not need a rigidbody in order to collide, but it does need a collider, as we have seen.
  • OnTriggerEnter: This occurs when an object has a collider, but the collider is set to be a trigger. A collider set to be a trigger will detect collisions, but then will allow the object to pass right through it. This is useful for things such as doors, portals, or other areas you want to detect when an object enters.

As you have already suspected, we will be using OnCollisionEnter to determine when our objects collide. However, instead of writing a single script for each object we want to check for collisions, we will instead implement a collision event system. The problem with writing a collision script for each object is that you will often end up with duplicate code, in different scripts attached to various objects. Each script then often manages its own collisions but often has different rules depending on what object it collides with. Take a look at the following diagram that shows how this may work:

Checking for collisions

Example of hard-coded collision scripts

As you can see in the diagram, the Monster and Plane objects both need some of the same code to handle a ball collision. Additionally, the ball object needs to react differently to its hits on the Monster or Plane. If we add more objects to the scene, we would need to expand that script to account for each object collision. We want a generalized way of acting and reacting to collisions that is also extensible.

Instead of writing three custom scripts in order to manage the collisions in our scene, we will use two, one for the collision (action) and another for the object's reaction. The scripts are aptly named CollisionAction and CollisionReaction, and a revised diagram showing them attached to the scene objects is as follows:

Checking for collisions

CollisionAction and CollisionReaction scripts used in scene

Before taking a closer look at the script code, we will add the collision scripts to the scene. Perform the following instructions to add the scripts to the objects:

  1. Go back to the Unity editor and open the Assets/FoodyGo/Scripts/PhysicsExt folder in the Project window. You will see the CollisionAction and CollisionReaction scripts in the folder.
  2. Drag and drop the CollisionAction script onto the CatchBall object in the Hierarchy window. If you don't see the CatchBall object, just expand the CatchScene object.
  3. Drag and drop the CollisionReaction script onto the CatchMonster and Plane objects in the Hierarchy window.
  4. Select the Plane object in the Hierarchy window.
  5. In the Inspector window, change the Collision Reaction component to match the following screenshot:

    Checking for collisions

    The Collision Reaction component settings

  6. Note that we are setting the name of the object (CatchBall) we want this component to manage reactions for. By checking Destroy Object, we make sure that the ball will now be destroyed when it hits the Plane. Don't worry about setting the particle settings just yet; we will get to that shortly.
  7. Select the CatchMonster object in the Hierarchy window and repeat step 4.
  8. Run the game in the editor by pressing Play. Test the collision scripts by throwing the ball at the monster and plane. When the ball hits the monster or plane now, it immediately gets destroyed.

As you saw, it was fairly simple to set up those collision scripts. You may expect those scripts to be quite complex, but fortunately they are quite simple. Open up the scripts in the editor of your choice, and we will review them:

  • CollisionAction: This script is attached to objects that are intended to collide with other objects, such as our ball or bullets and so on. The script detects a collision and then notifies objects with a CollisionReaction component that a collision occurred. Let's take a look at the OnCollisionEnter method:
            void OnCollisionEnter(Collision collision) 
            { 
                if (disarmed == false) 
                { 
                   reactions =
                   collision.gameObject.GetComponents<CollisionReaction>();  
           if(reactions != null && reactions.Length>0) 
            { 
               foreach (var reaction in reactions) 
               { 
                  if (gameObject.name.StartsWith
                  (reaction.collisionObjectName)) 
                  { 
                      reaction.OnCollisionReaction(gameObject, collision); 
                  } 
                } 
             }           
         } 
     }       
    

    This method doesn't actually manage the collision. Instead, it notifies the CollisionReaction components of the other object it collided with. First, it makes sure that the object is not disarmed. An object is armed when a player engages it and throws it. Next, it grabs all the CollisionReaction components that may be on the collision object. An object may have multiple CollisionReaction components attached that react differently for each object. After that, it loops through all the collision reactions and makes sure that object wants to handle collisions by testing the collisionObjectName. If it does, then it calls the OnCollisionReaction method.

    Tip

    We will use game object names here to filter the object collisions. A better implementation would be to use Tags. It will be up to the reader to be diligent and make that change by themselves.

  • CollisionReaction: This handles the messy details of what happens when an object collides with it; the code is fairly straightforward:
            public void OnCollisionReaction(GameObject go,
            Collision collision) 
            { 
               ContactPoint contact = collision.contacts[0]; 
               Quaternion rot = Quaternion.FromToRotation(Vector3.up,
               contact.normal); 
               Vector3 pos = contact.point; 
     
               if (particlePrefab != null) 
               { 
                  var particle = (Transform)Instantiate(particlePrefab,
                  pos, rot); 
                  Destroy(particle.gameObject, destroyParticleDelaySeconds); 
               } 
     
               if (destroyObject) 
               { 
                   Destroy(go, destroyObjectDelaySeconds); 
               } 
     
               collisionEvent.Invoke(gameObject, collision); 
             }        
    

    Tip

    This is a simple implementation of the CollisionReaction script, but it could be extended or inherited in order to apply other generalized effects, such as decals, damage, and so on.

    The first part of the code determines the impact point and direction of the collision. Then, it checks whether a particlePrefab is set. If it is, it instantiates the prefab at the impact point. Then, it calls the Destroy method with a delay defined in the properties. Next, it checks whether the colliding object should be destroyed. If so, it destroys the object after a delay is defined in the settings. Finally, a Unity Event called collisionEvent is invoked, and the collision is passed on to any listeners of that event. This allows for other custom scripts to subscribe to this event and handle the collision additionally, as needed. We will use this event to handle the freezing effects on the Monster later.

  • CollisionEvent: At the bottom of the CollisionReaction script, there is another class definition for CollisionEvent : UnityEvent<GameObject, Collision>, which is just empty. This is the definition for a custom Unity Event we use to notify other scripts or components that a collision has occurred. Unity Event is similar to the C# event or delegate pattern we used earlier but is slower in performance. However, Unity Events can easily be wired up between components in the editor rather than hardcoded in a script, which is essential for any script we want to generalize.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.81.58