예제 #1
0
    //轉身讓視野進行範圍的掃描,原地停留
    protected virtual void Scan()
    {
        if (scanTimer == 0)
        {
            navAgent.destination = myTransform.position;
            scanTimer            = Time.time;
            //決定這次scan的方向
            switch (Random.Range(0, 2))
            {
            case 0:
                scanAngle = RotationSpeed * -1;
                break;

            case 1:
                scanAngle = RotationSpeed;
                break;

            default:
                break;
            }
        }
        else if (Time.time - scanTimer > scanTimeStep)
        {
            //搜索結束
            scanTimer = 0;
        }
        //轉身搜索
        rotationAngle = scanAngle;
        //myTransform.Rotate(Vector3.up, scanAngle* UPDATE_INTERVAL);
        if (animationController != null)
        {
            animationController.PlayScan();
        }
        state = NPCMotion.Deciding;
    }
예제 #2
0
    //定點守備
    protected virtual void Garrison()
    {
        if (garrisonTarget != null)
        {
            if (garrisonTarget.CompareTag(Tags.DeadBody))
            {
                GarrisonTarget = null;
                state          = NPCMotion.Deciding;
            }
            else
            {
                InGarrison = Vector3.ProjectOnPlane(myTransform.position - GarrisonTarget.position, Vector3.up).magnitude < garrisonRange;

                if ((myTransform.position - garrisonTarget.position).magnitude < navAgent.stoppingDistance && navAgent.remainingDistance == 0)
                {
                    state = NPCMotion.Idle;
                }
                else
                {
                    mainTarget = garrisonTarget;
                    state      = NPCMotion.Move;
                }
            }
        }
        else
        {
            state = NPCMotion.Deciding;
        }
    }
예제 #3
0
    //待命
    protected virtual void Idle()
    {
        if (animationController != null)
        {
            animationController.PlayIdle();
        }
        navAgent.destination = myTransform.position;

        //else
        //{
        if (!IsGarrison && mainTarget == null && !isGuardPlayer)
        {
            //索敵
            float seed = Random.Range(0, CHANCE_TO_SEARCH_WIS_RATIO);
            //機率進入索敵狀態
            if (Time.time - _searchTimer > SearchTime + .1f && seed < status.GetPrimaryAttrubute(PrimaryAttributeName.Wisdom).AdjustedValue)
            {
                _searchTimer = 0;
                state        = NPCMotion.Search;
            }
            else
            {
                state = NPCMotion.Deciding;
            }
        }
        else
        {
            state = NPCMotion.Deciding;
        }
        //}
    }
예제 #4
0
 protected virtual void onTriggerExit(Collider other)
 {
     if (_targetsInVision.Contains(other.transform))
     {
         _targetsInVision.Remove(other.transform);
         CheckTarget();
         state = NPCMotion.Deciding;
     }
     //}
 }
예제 #5
0
    protected virtual void onTriggerEnter(Collider other)
    {
        if (other.GetComponent <Damagable>() != null)
        {
            _targetsInVision.Add(other.transform);

            CheckTarget();
            //_targetInVision = other.transform;
            state = NPCMotion.Deciding;
        }
    }
예제 #6
0
 //護衛目標附近徘徊,太遠會回來,無護位目標則遊蕩
 protected virtual void Search()
 {
     if (npc.IsCasting)
     {
         state = NPCMotion.Casting;
         return;
     }
     if (_searchTimer == 0)
     {
         if (guardTarget != null && Vector3.ProjectOnPlane((myTransform.position - guardTarget.position), Vector3.up).magnitude > PatrolMaxDistance)
         {
             //Debug.Log(SearchCenterPosition);
             float angle = Vector3.Angle(
                 Vector3.ProjectOnPlane(myTransform.forward, Vector3.up), Vector3.ProjectOnPlane(guardTarget.position - myTransform.position, Vector3.up)) *
                           (Vector3.Dot(myTransform.right, guardTarget.position - myTransform.position) > 0 ? 1 : -1);
             myTransform.Rotate(Vector3.up, angle);
             //rotationAngle = angle;
         }
         else
         {
             //隨機轉身
             myTransform.Rotate(Vector3.up, Random.Range(0, 360));
             //rotationAngle = Random.Range(0, 360);
         }
         searchTo     = myTransform.position + myTransform.forward * MoveSpeed * SearchTime;
         _searchTimer = Time.time;
     }
     else
     {
         if (Time.time - _searchTimer > SearchTime)
         {
             //索敵結束,重新判斷
             state    = NPCMotion.Deciding;
             searchTo = null;
         }
         else
         {
             //索敵時間中往該方向前進
             state = NPCMotion.Search;
         }
     }
     if (searchTo != null)
     {
         navAgent.destination = (Vector3)searchTo;
         if (animationController != null)
         {
             animationController.PlayWalk();
         }
     }
 }
예제 #7
0
 //施法中,原地停留
 protected virtual void Casting()
 {
     if (npc.IsCasting)
     {
         navAgent.destination = transform.position;
         state = NPCMotion.Casting;
         if (animationController != null)
         {
             animationController.PlayCast();
         }
     }
     else
     {
         state = NPCMotion.Deciding;
     }
 }
예제 #8
0
    //網主要目標移動
    protected virtual void Move()
    {
        if (npc.IsCasting)
        {
            state = NPCMotion.Casting;
            return;
        }
        //Debug.Log(GetComponent<NPCController>().IsAttacking +" || "+ GetComponent<NPCController>().IsSkilling);
        if (npc.IsAttacking || npc.IsSkilling)
        {
            state = NPCMotion.Deciding;
            return;
        }

        navAgent.destination = mainTarget.position - mainTarget.forward * -1 * MinDistance;
        if (animationController != null)
        {
            animationController.PlayRun();
        }

        state = NPCMotion.Deciding;
    }
예제 #9
0
    protected virtual void Awake()
    {
        myTransform      = transform;
        state            = NPCMotion.Idle;
        isAlive          = true;
        _targetsInVision = new List <Transform>();
        CommandTargets   = new List <Transform>();
        //NPCType = Type;
        _searchTimer = 0;
        controller   = GetComponent <CharacterController>();
        GameObject visionObject = new GameObject("Vision");

        visionObject.transform.parent   = myTransform;
        visionObject.transform.position = myTransform.position;
        VisionCollision visionCollision = visionObject.AddComponent <VisionCollision>();

        visionCollision.onTriggerEnter += onTriggerEnter;
        visionCollision.onTriggerExit  += onTriggerExit;
        vision           = visionObject.AddComponent <SphereCollider>();
        vision.center    = controller.center;
        vision.isTrigger = true;
    }
예제 #10
0
    //轉向主要目標,決定是否靠近
    protected virtual void Follow()
    {
        if (npc.IsCasting)
        {
            state = NPCMotion.Casting;
            return;
        }
        //有跟隨對象
        if (mainTarget)
        {
            //轉往目標方向
            //float angle = RotationSpeed * (Vector3.Dot(myTransform.right, mainTarget.position - myTransform.position) > 0 ? 1 : -1);
            float angle = Vector3.Angle(myTransform.forward, Vector3.ProjectOnPlane(mainTarget.position - myTransform.position, myTransform.up)) * (Vector3.Dot(myTransform.right, mainTarget.position - myTransform.position) > 0 ? 1 : -1);
            rotationAngle = angle;
            //myTransform.Rotate(Vector3.up, angle);
            //目標體寬
            var targetWidth = mainTarget.GetComponentInParent <Build>() != null?mainTarget.GetComponent <MeshFilter>().mesh.bounds.size.x *mainTarget.transform.localScale.x : mainTarget.GetComponent <CharacterController>().radius;

            //是否已經進入視當的距離
            if (Vector3.Distance(mainTarget.position, myTransform.position) < MinDistance + targetWidth)
            {
                //已經進入視當的距離,停下來
                navAgent.destination = myTransform.position;
                //Debug.Log("Stop");
                state = NPCMotion.Idle;
            }
            else
            {
                //沒進入視當的距離,繼續移動
                state = NPCMotion.Move;
            }
        }
        else
        {
            //無跟隨對象,待機
            state = NPCMotion.Deciding;
        }
    }
예제 #11
0
    //決策
    protected virtual void Deciding()
    {
        if (npc.IsCasting)
        {
            state = NPCMotion.Casting;
        }
        else
        {
            CheckTarget();
            npc.attackTarget = null;
            //有目標
            if (mainTarget != null)
            {
                if (IsGarrison &&
                    Vector3.ProjectOnPlane(mainTarget.position - GarrisonTarget.position, Vector3.up).magnitude > garrisonRange)
                {
                    state = NPCMotion.Garrison;
                }
                else
                {
                    if (guardTarget != null)
                    {
                        //攻擊目標超出護位目標時往護位目標移動,追擊1.5被距離
                        if (Vector3.ProjectOnPlane(
                                (mainTarget.position - guardTarget.position), Vector3.up).magnitude
                            > (isGuardPlayer ? PatrolCharMaxDistance : PatrolMaxDistance) * 1.5F)
                        {
                            mainTarget = guardTarget;
                            state      = NPCMotion.Move;
                            return;
                        }
                    }
                    bool mainTargetOutOfRange = false;
                    if (mainTarget.GetComponentInParent <Build>() == null)
                    {
                        //距離外的人
                        mainTargetOutOfRange = !_targetsInVision.Contains(mainTarget);
                    }
                    bool mainTargetOutOfVision = Mathf.Abs(Vector3.Angle(    //視野外
                                                               Vector3.ProjectOnPlane(
                                                                   mainTarget.position - myTransform.position, myTransform.up), myTransform.forward))
                                                 > VisionWidth && (mainTarget.position - myTransform.position).magnitude >= MinDistance * 2;
                    if (mainTargetOutOfRange)
                    {
                        //超出距離,靠過去
                        state = NPCMotion.Fallow;
                    }
                    else
                    {
                        //距離內
                        if (mainTargetOutOfVision)
                        {
                            //視線外,尋找
                            state = NPCMotion.Scan;
                        }
                        else
                        {
                            //視線內,跟上
                            state            = NPCMotion.Fallow;
                            npc.attackTarget = mainTarget;
                        }
                    }
                }
            }
            else
            {
                if (IsGarrison)
                {
                    state = NPCMotion.Garrison;
                }
                else
                {
                    //沒有主要目標
                    //有護衛目標時
                    if (guardTarget != null)
                    {
                        //超出護位目標時往護位目標移動
                        if (Vector3.ProjectOnPlane((myTransform.position - guardTarget.position), Vector3.up).magnitude > (isGuardPlayer? PatrolCharMaxDistance: PatrolMaxDistance))
                        {
                            mainTarget = guardTarget;
                            state      = NPCMotion.Move;
                        }
                        else
                        {
                            //靠近護位目標時護位待命

                            state = NPCMotion.Idle;
                        }
                    }
                    else
                    {
                        //無護位目標時待命
                        if (npc.commander != null)
                        {
                            //npc.commander.CommandFollowerInvade(npc);
                            if (npc.commander is Tower)
                            {
                                npc.Patrol((npc.commander as Tower).MainFlag);
                            }
                            else if (npc.commander is Player)
                            {
                                npc.Patrol((npc.commander as Player).myTransform);
                            }

                            state = NPCMotion.Deciding;
                        }
                        else
                        {
                            state = NPCMotion.Idle;
                        }
                    }
                }
            }
        }
    }