The smelling function using a collider-based system

Smelling is one of the trickiest senses to translate from the real to the virtual world. There are several techniques, but most of them are inclined to the use of colliders or graph logic.

Smelling can be simulated by computing a collision between an agent and odor particles scattered throughout the game level.

Getting ready

As with the other recipes based on colliders, we will need collider components attached to every object that is to be checked, and rigid body components attached to either emitters or receivers.

How to do it…

We will develop the scripts for representing odor particles and agents that are able to smell:

  1. Create the particle's script and define its member variables for computing its lifespan:
    using UnityEngine;
    using System.Collections;
    
    public class OdourParticle : MonoBehaviour
    {
        public float timespan;
        private float timer;
    }
  2. Implement the Start function for proper validations:
    void Start()
    {
        if (timespan < 0f)
            timespan = 0f;
        timer = timespan;
    }
  3. Implement the timer and destroy the object after its lifecycle:
    void Update()
    {
        timer -= Time.deltaTime;
        if (timer < 0f)
            Destroy(gameObject);
    }
  4. Create the class for representing the sniffer agent:
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class Smeller : MonoBehaviour
    {
        private Vector3 target;
        private Dictionary<int, GameObject> particles;
    }
  5. Initialize the dictionary for storing odor particles:
    void Start()
    {
        particles = new Dictionary<int, GameObject>();
    }
  6. Add to the dictionary the colliding objects that have the odor-particle component attached:
    public void OnTriggerEnter(Collider coll)
    {
        GameObject obj = coll.gameObject;
        OdourParticle op;
        op = obj.GetComponent<OdourParticle>();
        if (op == null)
            return;
        int objId = obj.GetInstanceID();
        particles.Add(objId, obj);
        UpdateTarget();
    }
  7. Release the odor particles from the local dictionary when they are out of the agent's range or are destroyed:
    public void OnTriggerExit(Collider coll)
    {
        GameObject obj = coll.gameObject;
        int objId = obj.GetInstanceID();
        bool isRemoved;
        isRemoved = particles.Remove(objId);
        if (!isRemoved)
            return;
        UpdateTarget();
    }
  8. Create the function for computing the odor centroid according to the current elements in the dictionary:
    private void UpdateTarget()
    {
        Vector3 centroid = Vector3.zero;
        foreach (GameObject p in particles.Values)
        {
            Vector3 pos = p.transform.position;
            centroid += pos;
        }
        target = centroid;
    }
  9. Implement the function for retrieving the odor centroids, if any:
    public Vector3? GetTargetPosition()
    {
        if (particles.Keys.Count == 0)
            return null;
        return target;
    }

How it works…

Just like the hearing recipe based on colliders, we use the trigger colliders in order to register odor particles in an agent's perception (implemented using a dictionary). When a particle is included or removed, the odor centroid is computed. However, we implement a function for retrieving that centroid because when no odor particle is registered, the internal centroid position is not updated.

How it works…

There is more…

Particle emission logic is left behind to be implemented according to our game's needs, and it's basically instantiating odor-particle prefabs. Also, it is recommended that you attach the rigid-body components to the agents. Odor particles are prone to be massively instantiated, reducing the game's performance.

..................Content has been hidden....................

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