Created
March 11, 2021 01:40
-
-
Save IndieGameMaker/34dcc3242c8b4c2aec670620b07d2a8e to your computer and use it in GitHub Desktop.
[스크립트 8 11] MonsterCtrl - 스코어 점수 누적시키는 로직
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
//내비게이션 기능을 사용하기 위해 추가해야 하는 네임스페이스 | |
using UnityEngine.AI; | |
public class MonsterCtrl : MonoBehaviour | |
{ | |
//몬스터의 상태 정보 | |
public enum State | |
{ | |
IDLE, | |
TRACE, | |
ATTACK, | |
DIE | |
} | |
//몬스터의 현재 상태 | |
public State state = State.IDLE; | |
//추적 사정거리 | |
public float traceDist = 10.0f; | |
//공격 사정거리 | |
public float attackDist = 2.0f; | |
//몬스터의 사망 여부 | |
public bool isDie = false; | |
//컴포넌트 캐시 처리할 변수 | |
private Transform monsterTr; | |
private Transform playerTr; | |
private NavMeshAgent agent; | |
private Animator anim; | |
//Animator 파라미터의 해시값 추출 | |
private readonly int hashTrace = Animator.StringToHash("IsTrace"); | |
private readonly int hashAttack = Animator.StringToHash("IsAttack"); | |
private readonly int hashHit = Animator.StringToHash("Hit"); | |
private readonly int hashPlayerDie = Animator.StringToHash("PlayerDie"); | |
private readonly int hashSpeed = Animator.StringToHash("Speed"); | |
private readonly int hashDie = Animator.StringToHash("Die"); | |
//혈흔 효과 프리팹 | |
private GameObject bloodEffect; | |
//몬스터 생명 변수 | |
private int hp = 100; | |
//스크립트가 활성화 될 때마다 호출되는 함수 | |
void OnEnable() | |
{ | |
//이벤트 발생 시 수행할 함수 연결 | |
PlayerCtrl.OnPlayerDie += this.OnPlayerDie; | |
//몬스터의 상태를 체크하는 코루틴 함수 호출 | |
StartCoroutine(CheckMonsterState()); | |
//상태에 따라 몬스터의 행동을 수행하는 코루틴 함수 호출 | |
StartCoroutine(MonsterAction()); | |
} | |
//스크립트가 비활성화 될 때마다 호출되는 함수 | |
void OnDisable() | |
{ | |
//기존에 연결된 함수 해제 | |
PlayerCtrl.OnPlayerDie -= this.OnPlayerDie; | |
} | |
void Awake () | |
{ | |
//몬스터의 Transform 할당 | |
monsterTr = GetComponent<Transform>(); | |
//추적 대상인 Player의 Transform 할당 | |
playerTr = GameObject.FindWithTag("PLAYER").GetComponent<Transform>(); | |
//NavMeshAgent 컴포넌트 할당 | |
agent = GetComponent<NavMeshAgent>(); | |
//Animator 컴포넌트 할당 | |
anim = GetComponent<Animator>(); | |
//BloodSprayEffect 프리팹 로드 | |
bloodEffect = Resources.Load<GameObject>("BloodSprayEffect"); | |
} | |
//일정한 간격으로 몬스터의 행동 상태를 체크 | |
IEnumerator CheckMonsterState() | |
{ | |
while (!isDie) | |
{ | |
//0.3초 동안 중지(대기)하는 동안 제어권을 메시지 루프에 양보 | |
yield return new WaitForSeconds(0.3f); | |
//몬스터의 상태가 DIE일 때 코루틴을 종료 | |
if (state == State.DIE) yield break; | |
//몬스터와 주인공 캐릭터 사이의 거리 측정 | |
float distance = Vector3.Distance(playerTr.position, monsterTr.position); | |
//공격 사정거리 범위 이내로 들어왔는지 확인 | |
if (distance <= attackDist) | |
{ | |
state = State.ATTACK; | |
} | |
//추적 사정거리 범위 이내로 들어왔는지 확인 | |
else if (distance <= traceDist) | |
{ | |
state = State.TRACE; | |
} | |
else | |
{ | |
state = State.IDLE; | |
} | |
} | |
} | |
//몬스터의 상태에 따라 몬스터의 동작을 수행 | |
IEnumerator MonsterAction() | |
{ | |
while (!isDie) | |
{ | |
switch (state) | |
{ | |
//IDLE 상태 | |
case State.IDLE: | |
//추적 중지 | |
agent.isStopped = true; | |
//Animator의 IsTrace 변수를 false로 설정 | |
//anim.SetBool("IsTrace", false); | |
anim.SetBool(hashTrace, false); | |
break; | |
//추적 상태 | |
case State.TRACE: | |
//추적 대상의 좌표로 이동시작 | |
agent.SetDestination(playerTr.position); | |
agent.isStopped = false; | |
//Animator의 IsTrace 변수를 true로 설정 | |
//anim.SetBool("IsTrace", true); | |
anim.SetBool(hashTrace, true); | |
//Animator의 IsAttack 변수를 false로 설정 | |
anim.SetBool(hashAttack, false); | |
break; | |
//공격 상태 | |
case State.ATTACK: | |
//Animator의 IsAttack 변수를 true로 설정 | |
anim.SetBool(hashAttack, true); | |
break; | |
//사망 | |
case State.DIE: | |
isDie = true; | |
//추적 정지 | |
agent.isStopped = true; | |
//사망 애니메이션 실행 | |
anim.SetTrigger(hashDie); | |
//몬스터의 Collider 컴포넌트 비활성화 | |
GetComponent<CapsuleCollider>().enabled = false; | |
//일정시간 대기후 오브젝트 풀링으로 환원 | |
yield return new WaitForSeconds(3.0f); | |
//사망 후 다시 사용할 때를 위한 변숫값의 초기화 | |
hp = 100; | |
isDie = false; | |
state = State.IDLE; | |
//몬스터의 Collider 컴포넌트 활성화 | |
GetComponent<CapsuleCollider>().enabled = true; | |
//몬스터를 비활성화 | |
this.gameObject.SetActive(false); | |
break; | |
} | |
yield return new WaitForSeconds(0.3f); | |
} | |
} | |
void OnCollisionEnter(Collision coll) | |
{ | |
if (coll.collider.CompareTag("BULLET")) | |
{ | |
//충돌한 총알을 삭제 | |
Destroy(coll.gameObject); | |
//피격 리액션 애니메이션 실행 | |
anim.SetTrigger(hashHit); | |
//총알의 충돌 지점 | |
Vector3 pos = coll.GetContact(0).point; | |
//총알의 충돌지점의 법선 벡터 | |
Quaternion rot = Quaternion.LookRotation(-coll.GetContact(0).normal); | |
//혈흔 효과를 생성하는 함수 호출 | |
ShowBloodEffect(pos, rot); | |
//몬스터의 hp 차감 | |
hp -= 10; | |
if (hp <= 0) | |
{ | |
state = State.DIE; | |
//몬스터가 사망했을 때 50점을 추가 | |
GameManager.instance.DisplayScore(50); | |
} | |
} | |
} | |
//혈흔 효과를 생성하는 함수 | |
void ShowBloodEffect(Vector3 pos, Quaternion rot) | |
{ | |
//혈흔 효과 생성 | |
GameObject blood = Instantiate<GameObject>(bloodEffect, pos, rot, monsterTr); | |
Destroy(blood, 1.0f); | |
} | |
void OnDrawGizmos() | |
{ | |
//추적 사정거리 표시 | |
if (state == State.TRACE) | |
{ | |
Gizmos.color = Color.blue; | |
Gizmos.DrawWireSphere(transform.position, traceDist); | |
} | |
//공격 사정거리 표시 | |
if (state == State.ATTACK) | |
{ | |
Gizmos.color = Color.red; | |
Gizmos.DrawWireSphere(transform.position, attackDist); | |
} | |
} | |
void OnTriggerEnter(Collider coll) | |
{ | |
Debug.Log(coll.gameObject.name); | |
} | |
void OnPlayerDie() | |
{ | |
//몬스터의 상태를 체크하는 코루틴 함수를 모두 정지시킴 | |
StopAllCoroutines(); | |
//추적을 정지하고 애니메이션을 수행 | |
agent.isStopped = true; | |
anim.SetFloat(hashSpeed, Random.Range(0.8f, 1.2f)); | |
anim.SetTrigger(hashPlayerDie); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment