/**
     * Generate players and their traits according to the scriptable object distribution
     *
     */
    private GameObject createPlayer(bool isTeam0)
    {
        GameObject create;

        if (isTeam0)
        {
            Vector3 spawnlocation = team0.spawnOrigin + Random.onUnitSphere * team0.spawnRadius;
            create = Instantiate(playerPrefab, spawnlocation, Quaternion.identity);
            BoidPlayer boidPlayer = create.GetComponent <BoidPlayer>();
            boidPlayer.setTeamColor(team0.color);
            boidPlayer.team                = 0;
            boidPlayer.respawnPosition     = spawnlocation;
            boidPlayer.aggressiveness      = sampleGaussian(team0.agressivenessMean, team0.agressivenessSD);
            boidPlayer.maxExhaustion       = sampleGaussian(team0.maxExhaustionMean, team0.maxExhaustionSD);
            boidPlayer.maxVelo             = sampleGaussian(team0.maxVeloMean, team0.maxVeloSD);
            boidPlayer.weight              = sampleGaussian(team0.weightMean, team0.weightSD);
            boidPlayer.urge                = sampleGaussian(team0.urgeMean, team0.urgeSD);
            boidPlayer.thisSnitchWeight    = team0.snitchWeight;
            boidPlayer.thisCollisionWeight = team0.collisionAvoidanceWeight;

            if (Random.Range(0f, 1f) < team0.jokerSpawnChance)
            {
                // This player is a joker
                boidPlayer.isJoker = true;
                boidPlayer.setTeamColor(team0.jokerColor);
                boidPlayer.aggressiveness = 70f;
                boidPlayer.maxVelo        = 100f;
                boidPlayer.weight         = 2f;
            }
        }
        else
        {
            Vector3 spawnlocation = team1.spawnOrigin + Random.onUnitSphere * team1.spawnRadius;
            create = Instantiate(playerPrefab, spawnlocation, Quaternion.identity);
            BoidPlayer boidPlayer = create.GetComponent <BoidPlayer>();
            boidPlayer.setTeamColor(team1.color);
            boidPlayer.team                = 1;
            boidPlayer.respawnPosition     = spawnlocation;
            boidPlayer.aggressiveness      = sampleGaussian(team1.agressivenessMean, team1.agressivenessSD);
            boidPlayer.maxExhaustion       = sampleGaussian(team1.maxExhaustionMean, team1.maxExhaustionSD);
            boidPlayer.maxVelo             = sampleGaussian(team1.maxVeloMean, team1.maxVeloSD);
            boidPlayer.weight              = sampleGaussian(team1.weightMean, team1.weightSD);
            boidPlayer.urge                = sampleGaussian(team1.urgeMean, team1.urgeSD);
            boidPlayer.thisSnitchWeight    = team1.snitchWeight;
            boidPlayer.thisCollisionWeight = team1.collisionAvoidanceWeight;
            if (Random.Range(0f, 1f) < team1.jokerSpawnChance)
            {
                // This player is a joker
                boidPlayer.isJoker = true;
                boidPlayer.setTeamColor(team1.jokerColor);
                boidPlayer.aggressiveness = 70f;
                boidPlayer.maxVelo        = 100f;
                boidPlayer.weight         = 2f;
            }
        }
        return(create);
    }
    /**
     *
     * Handle four types of collisions:
     *   1. Arena environment
     *   2. Opponent
     *   3. Proponent
     *   4. Snitch
     *
     */
    void OnCollisionEnter(Collision collision)
    {
        // Create a collision listener to get the two instances of the collision

        if (collision.gameObject.CompareTag("Ground") && this.isUnconscious)
        {
            // Teleport to spawn point and hold for penalty
            gameObject.transform.position = respawnPosition;
            unconsciousPenalty            = Game.instance.unconsciousTimeHold;
            rigidbody.isKinematic         = true;
            onHold = true;
            if (Game.instance.debug)
            {
                Debug.Log("Hit ground. Respawning");
            }
        }

        else if (collision.gameObject.CompareTag("Snitch") && !isUnconscious)
        {
            Game.instance.score(this.team);
        }

        else if (collision.gameObject.CompareTag("Player") && !isUnconscious)
        {
            // Handle the case of double instances for OnCollisionEnter call
            if (collisionAlreadyHandled)
            {
                collisionAlreadyHandled = false;
                return;
            }
            // Do nothing if collides with other teammate and randomness fails past the 5% threshold
            BoidPlayer other = collision.gameObject.GetComponent <BoidPlayer>();
            other.collisionAlreadyHandled = true;
            if (other.team == this.team && Random.Range(0.0f, 1.0f) < 0.95)
            {
                return;
            }

            float myval    = this.aggressiveness * (Random.Range(0, 1) * (1.2f - 0.8f) + 0.8f) * (1 - (this.currentExhaustion / this.maxExhaustion));
            float otherval = other.aggressiveness * (Random.Range(0, 1) * (1.2f - 0.8f) + 0.8f) * (1 - (other.currentExhaustion / other.maxExhaustion));

            float low = Mathf.Min(myval, otherval);
            if (low == myval)
            {
                setUnconscious();
            }
            else
            {
                other.setUnconscious();
            }
        }
        else if (collision.gameObject.CompareTag("Terrain"))
        {
            // Considered Tackled and unconscious
            setUnconscious();
        }
    }