//플레이어 덮침 void MonCheckHoldDown() { m_Core.delayTime = 0.5f; //딜레이 설정 if (isFinTrace) //현재 추적을 끝내고 대기상태인지 { isFinTrace = false; //상태 변환 //확률에 따라 브레스 1과 점프 어택 중 택 1 Random.seed = (int)System.DateTime.Now.Ticks; //랜덤값의 시드를 무작위로 만든다 int randomChance = Random.Range(0, 1000); if (randomChance < 500) { alleySkillState = M_AlleySkillState.JumpAttack; StartCoroutine(M_JumpAttack.instance.UseSkill(alleyGateForwardPos)); //점프 어택으로 덮침 } else { alleySkillState = M_AlleySkillState.Breath; StartCoroutine(M_Breath.instance.UseSkill(alleyGateForwardPos)); //브레스로 덮침 } alleyState = M_AlleyState.Starting; //골목 스타트 상태로 변경 } }
//추적 체크 IEnumerator CheckTracing() { float timeCounter = 0.0f; isCheckTracing = true; while (true) { timeCounter += Time.deltaTime; //시간 계산 if (!isCheckTracing) //추적 검토가 외부에서 중단되었다면 { yield break; } if ((timeCounter > checkTimeToBreath_2) && //브레스 2 사용을 위한 체크 시간이 다 지나갔고 !m_Core.CheckSight().isPlayerInStraightLine) //캐릭터가 시야에 없다면 { isCheckTracing = false; //추적 검토 중단 isCheckingBreath_2 = false; //브레스 2 검토 중단 alleyState = M_AlleyState.Tracing; //추적으로 상태 변경 yield break; } yield return(new WaitForEndOfFrame()); } }
//골목 순찰 void Patrol() { //플레이어를 발견했다면 다시 Tracing으로 상태 변경 if (m_Core.CheckAuditoryField().isHearing) //플레이어가 청각 영역 안에 있으면 { alleyState = M_AlleyState.Tracing; //골목 외길 순찰로 상태 변경 } //현재 패트롤 지점으로 이동 m_Core.NvAgent.speed = originSpeed; m_Core.NvAgent.Resume(); m_Core.NvAgent.destination = nowPatrolingPos; m_Core.SetDestinationRealtime(false, null); m_Core.Animator.SetBool("IsRunning", true); if (Vector3.Distance(nowPatrolingPos, m_Core.Tr.position) < 1.0f) //패트롤 지점에 충분히 가까워졌다면 { if ((isStartPatroling) && (nowPatrolingPointIndex.Equals(patrolingEndIndex))) //첫 지점 통과 후, 도착 지점에 도달한 것이면 { m_Core.ChangeState(M_Patrol.instance); //순찰상태로 변경 } //다음으로 이동할 waypoint Index 지정 if (isPatrolingClockwise) { nowPatrolingPointIndex++; //현재 패트롤할 인덱스 증가 if (nowPatrolingPointIndex > alleyBigTrigger.patrolWayPoints.Length - 1) //패트롤 인덱스가 범위를 벗어나게 되면 { nowPatrolingPointIndex = 0; //0번부터 다시 } } else { nowPatrolingPointIndex--; //현재 패트롤할 인덱스 감소 if (nowPatrolingPointIndex < 0) //패트롤 인덱스가 범위를 벗어나게 되면 { nowPatrolingPointIndex = alleyBigTrigger.patrolWayPoints.Length - 1; //마지막부터 다시 } } isStartPatroling = true; //첫 지점 통과했습니다! //다음으로 이동할 Index에 맞는 waypoint 위치 지정 nowPatrolingPos = alleyBigTrigger.patrolWayPoints[nowPatrolingPointIndex].position; } }
//상태 진입 public override void Enter() { //진입점이 대기 또는 순찰상태였다면 플레이어와 실 거리가 가장 가까운 입구쪽을 목표 지점으로 시작한다 if (isStartToIdleOrPatrol) { isStartToIdleOrPatrol = false; //목적지까지의 경로를 구함 NavMeshPath path = new NavMeshPath(); //플레이어와 가까운 쪽의 Gate에 저장된 Pos를 목적지로 함 float minTriggerDist = 10000; for (int i = 0; i < alleyBigTrigger.gateTrigger.Length; i++) { NavMesh.CalculatePath(m_Core.PlayerTr.position, alleyBigTrigger.gateTrigger[i].GetComponent <Transform>().position, NavMesh.AllAreas, path); float tempDist = 0; tempDist += Vector3.Distance(m_Core.PlayerTr.position, path.corners[0]); //현재 플레이어 위치에서 경로 첫 지점까지의 거리부터 더하기 시작 for (int j = 0; j < path.corners.Length - 2; j++) //경로 지점의 선분 갯수만큼 반복하며 { //저장된 경로를 따라 경로 지점 사이의 거리를 구해 총 거리를 계산한다 tempDist += Vector3.Distance(path.corners[j], path.corners[j + 1]); } if (tempDist < minTriggerDist) { minTriggerDist = tempDist; //정보 갱신 alleyGateTrigger = alleyBigTrigger.gateTrigger[i]; //으 브레스땜시 어쩔 수 없긴 한데 넘 더럽다 이거 분명 다른데에서 더 깔끔하게 가져올 수 있을텐데 일단은 alleyGateTriggerPos = alleyBigTrigger.gateTrigger[i].GetComponent <Transform>().position; alleyGateForwardPos = alleyBigTrigger.gateTrigger[i].GetComponent <O_AlleyGateTrigger>().gateForwardPos.position; alleyInCornerPos = alleyBigTrigger.gateTrigger[i].GetComponent <O_AlleyGateTrigger>().inCornerPos.position; } } } originSpeed = m_Core.NvAgent.speed; alleyState = M_AlleyState.Starting; //Starting상태로 시작 //////Debug.Log("Enter Alley"); }
//골목 안쪽을 확인 IEnumerator CheckInAlley() { yield return(StartCoroutine(RotateToPoint(m_Core.transform, targetGatePos, lookRotationTime))); //<<추가>> 시야에 보이면 다시 골목 시작부터, 아님 패트롤 시켰는데 우쩔까용 if (m_Core.CheckSight().isPlayerInStraightLine) //플레이어가 직선거리 상에 위치하고 있으면 { //정보 갱신 alleyGateTriggerPos = targetGatePos; alleyGateForwardPos = targetGateForwardPos; alleyInCornerPos = targetCornerPos; alleyState = M_AlleyState.Starting; //골목 시작 상태로 변경 } else { SelectStartPatrol(); alleyState = M_AlleyState.Patrol; //골목 순찰 상태로 변경 } }
//골목 상태 시작 void Starting() { if (Vector3.Distance(m_Core.Tr.position, alleyGateForwardPos) < 1.0f) //도착지점과의 거리가 충분히 가까워지면 { m_Core.NvAgent.speed = originSpeed; m_Core.NvAgent.Stop(); m_Core.SetDestinationRealtime(false, null); m_Core.Animator.SetBool("IsRunning", false); alleyState = M_AlleyState.InSight; //시야 안으로 상태 변경 } else //도착지점까지의 거리가 충분히 가깝지 않다면 { //골목으로 플레이어를 추격 m_Core.NvAgent.speed = alleyTracingSpeed; m_Core.NvAgent.Resume(); m_Core.NvAgent.destination = alleyGateForwardPos; m_Core.SetDestinationRealtime(false, null); m_Core.Animator.SetBool("IsRunning", true); } }
//플레이어가 보이지 않아 추격 void Tracing() { m_Core.delayTime = 0.2f; //업데이트 주기 설정 //플레이어가 청각 영역 안에 있으면 if (m_Core.CheckAuditoryField().isHearing) { //플레이어와 가까운 쪽의 Gate에 저장된 Pos를 목적지로 함 NavMeshPath path = new NavMeshPath(); float minTriggerDist = 10000; for (int i = 0; i < alleyBigTrigger.gateTrigger.Length; i++) { NavMesh.CalculatePath(m_Core.PlayerTr.position, alleyBigTrigger.gateTrigger[i].GetComponent <Transform>().position, NavMesh.AllAreas, path); float tempDist = 0; tempDist += Vector3.Distance(m_Core.PlayerTr.position, path.corners[0]); for (int j = 0; j < path.corners.Length - 2; j++) { tempDist += Vector3.Distance(path.corners[j], path.corners[j + 1]); } if (tempDist < minTriggerDist) { minTriggerDist = tempDist; targetGatePos = alleyBigTrigger.gateTrigger[i].GetComponent <Transform>().position; targetCornerPos = alleyBigTrigger.gateTrigger[i].GetComponent <O_AlleyGateTrigger>().inCornerPos.position; targetGateForwardPos = alleyBigTrigger.gateTrigger[i].GetComponent <O_AlleyGateTrigger>().gateForwardPos.position; } } //목적지까지의 path 경로 구함 if (m_Core.NvAgent.enabled) { m_Core.NvAgent.CalculatePath(targetGateForwardPos, path); } //경로의 코너가 3개 이하이며, 일정 거리 이내로 목적지에 들어왔을 때 if ((path.corners.Length < 3) && (Vector3.Distance(m_Core.Tr.position, targetGateForwardPos) < finTraceDist)) { //기습 대기중 체크 isFinTrace = true; m_Core.NvAgent.speed = originSpeed; m_Core.NvAgent.Stop(); m_Core.SetDestinationRealtime(false, null); m_Core.Animator.SetBool("IsRunning", false); //대기 시간이 일정 시간이 넘어가면 finTraceWaitTimeCounter += Time.deltaTime + 0.2f; if (finTraceWaitTimeCounter > finTraceWaitTimeLimit) { isFinTrace = false; finTraceWaitTimeCounter = 0; alleyState = M_AlleyState.NoWait; //보스 골목 안쪽 바라보기 상태로 변경 } } else { //기습 위해 이동 isFinTrace = false; m_Core.NvAgent.speed = alleyTracingSpeed; m_Core.NvAgent.Resume(); m_Core.NvAgent.destination = targetGateForwardPos; m_Core.SetDestinationRealtime(false, null); m_Core.Animator.SetBool("IsRunning", true); finTraceWaitTimeCounter = 0; } } //플레이어의 위치를 아예 잃어버렸다면 else { SelectStartPatrol(); alleyState = M_AlleyState.Patrol; //골목 외길 순찰로 상태 변경 } }