Interaction with player. Log #9 (C#)
01.05.2017

        There are going to be 3 kinds of entities in Alots. Neutral, aggressive and neutral-aggressive. Nutral won't attack player until the player attacks first, then entity will try to fight until the player is at sight. Aggressive attacks immidiately as the player is at sight, and stops following him only when the player is out of the sight. Neutral-aggressive has two states, first state is only warning for player to not to come closer, second is same as aggressive state. As entity is considered every living being in game, also player character, but player is unique entity having different behaviour than other entities. But all entities are objects.

          And as I said earlier, all objects in game will have its own radius, but it would be redundant to have radius in every script, so I will create superior class BasicObject in Scripts, which will inherit from class MonoBehaviour and each object will be subclass of BasicObject. This class will have one property StoppingDistance for now. Now I'll create script Entity (Scripts>Entities) and rename parent class to BasicObject. For differentiate between entity type I'll create enumerator EntityType.

 

public enum EntityType
{
	Neutral,    //0
	Aggresive,  //1
	NeutralAggresive, //2
}

 

          Entity of course needs acces to its controller, to know what to do. Interaction with player interfers with patrolling system. To attack, entity needs to stop patrolling, eventually return back to patrolling after player is out of sight. For neutral aggressive type, in first state will entity just pause patrolling, and if player retreats, entity will continue patrolling.

          Each entity, like mouse or any creature has defined EntityType which I will set in constructor of each creature, along with other attributes as lives, strength, etc. In function Update() of Entity class I'll create switch which will dvide entity behaviour by its type. In case of neutral behaviour I need to know if player attacked the crature. Simply by function OnMouseOver() and TookDamage() called in PlayerController (not inplemented yet).

 

void OnMouseOver()
{
     if (Input.GetMouseButton(1))
     {
        selected = true;
     }
}

public void TakeDamage(float damage)
{
     tookDamage = true;
}

 

          If both conditions are true it will stop patrolling. In case of neutral entity, after the player attack will creature become "upset" and its radius for getting out of sight, will double. Then I check if player is at sight. If he is, entity will move towards him, if not, entity will return to patrolling. Into EntityController is required to implement functions MoveTowardsPlayer() and ResumePatrol()

 

public void MoveTowardsPlayer()
{
    nma.stoppingDistance = 2f;
    nma.SetDestination(player.position);
    nma.Resume();
    movingTowardsPlayer = true;
    playerReached = false;
    playerInteraction = true;
}

public void ResumePatrol()
{
    movingTowardsPlayer = false;
    playerInteraction = false;
    nma.stoppingDistance = 0.1f;
    EntityToWaypointDistance();
    StartPatrol(waypoints[waypointIndex]);
}

 

          Boolean variables are only for defferentiate between entity interaction with player and patrolling. MoveTowardsPlayer() is almost the same as starting patrol, only in this function is needed to set the stoppingDistance for creature to stop in plausible distance. Function ResumePatrol() just ends any interaction with player and returns entity to patrolling. That's all for EntityController.

          For aggressive behaviour is approach similar as for neutral. For aggressive neutral behaviour is required to swap conditions. So first state is, when player comes into first radius, then entity pauses patrolling and warns player. If player comes into "aggressive radius", entity will attack and its EntityRadius aquires the size of "warning radius".

 

new protected void Update()
    {
        base.Update();

        if (ec != null)
        {
            switch (Type)
            {
                case EntityType.Neutral:                       //Neutral Behaviour
                    if (selected)
                    {
                        if (tookDamage)
                        {
                            ec.StopPatrol();

                            if (!largedRadius)
                            {
                                EntityRadius *= 2;
                                largedRadius = true;
                            }

                            if (ec.IsPlayerInRange(EntityRadius))
                            {
                                if (ec.IsPlayerReached())
                                {
                                    //Attack
                                }
                                else
                                {
                                    ec.MoveTowardsPlayer();
                                }
                            }
                            else
                            {
                                ec.ResumePatrol();
                            }
                        }
                    }
                    break;
                case EntityType.Aggresive:                    //Agressive Behaviour
                    if (ec.IsPlayerInRange(EntityRadius))
                    {
                        ec.StopPatrol();
                        if (ec.IsPlayerReached())
                        {
                            //Attack
                        }
                        else
                        {
                            ec.MoveTowardsPlayer();
                        }
                    }
                    else if (!ec.IsPatrolPending())
                    {
                        ec.ResumePatrol();
                    }
                    break;
                case EntityType.NeutralAggresive:            //NeutralAggressive Behaviour
                    if (ec.IsPlayerInRange(NeutralAgressiveRadius))
                    {
                        ec.StopPatrol();
                        if (ec.IsPlayerReached())
                        {
                            //Attack
                        }
                        else if(ec.IsPlayerInRange(EntityRadius))
                        {
                            EntityRadius = NeutralAgressiveRadius;
                            Type = EntityType.Aggresive;
                        }
                    }
                    else if (!ec.IsPatrolPending())
                    {
                        ec.ResumePatrol();
                    }
                    break;
            }
        }
    }

 

There is necessary to have EntityController instance.

 

new protected void Start()
{
    ec = GetComponent<EntityController>();
    transform.tag = "Entity";

}

 

 

As you can see, entities are green by default, in case when player comes into EntityRadius, entities will become red, if player is in "warning radius" entity will become yellow. Those are equivalent colors for action StopPatrol() - yellow, MoveTowardsPlayer() - red and cyan color represents entity returning to patrolling (ResumePatrol()).