using System;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 1f;
[SerializeField]
private float turnSpeed = 150f;
[SerializeField]
private Transform mainCamera;
private Animation anim;
private Transform tr;
private readonly float initHp = 100.0f;
public float currHp;
public delegate void PlayerDieHandler();
public static event PlayerDieHandler OnPlayerDie;
public enum eAnimState
{
Idle,
RunB,
RunF,
RunL,
RunR
}
private void Start()
{
currHp = initHp;
this.tr = this.GetComponent<Transform>();
this.anim = this.GetComponent<Animation>();
this.anim.clip = this.anim.GetClip(eAnimState.Idle.ToString());
this.anim.Play();
if (mainCamera == null)
{
mainCamera = Camera.main.transform;
}
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
private void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
float mouseX = Input.GetAxis("Mouse X");
var dir = new Vector3(h, 0, v);
Vector3 moveDir = (Vector3.forward * v) + (Vector3.right * h);
this.transform.Translate(moveDir.normalized * this.moveSpeed * Time.deltaTime);
tr.Rotate(Vector3.up * mouseX * turnSpeed * Time.deltaTime);
this.PlayAnimation(dir);
if (mainCamera)
{
mainCamera.LookAt(tr.position);
}
}
private void PlayAnimation(Vector3 dir)
{
if (dir.x > 0)
{ //right
this.anim.CrossFade(eAnimState.RunR.ToString(), 0.25f);
}
else if (dir.x < 0)
{ //left
this.anim.CrossFade(eAnimState.RunL.ToString(), 0.25f);
}
else if (dir.z > 0)
{
//forward
this.anim.CrossFade(eAnimState.RunF.ToString(), 0.25f);
}
else if (dir.z < 0)
{
//back
this.anim.CrossFade(eAnimState.RunB.ToString(), 0.25f);
}
else
{
//idle
this.anim.CrossFade(eAnimState.Idle.ToString(), 0.25f);
}
}
private void OnTriggerExit(Collider other)
{
if(currHp >= 0.0f && other.CompareTag("PUNCH"))
{
currHp -= 10.0f;
Debug.Log("Player hp = " + currHp/initHp);
if(currHp <= 0.0f)
{
PlayerDie();
}
}
}
void PlayerDie()
{
Debug.Log("Player Die!");
//GameObject[] monsters = GameObject.FindGameObjectsWithTag("Monster");
//foreach (GameObject monster in monsters)
//{
// monster.SendMessage("OnPlayerDie", SendMessageOptions.DontRequireReceiver);
//}
OnPlayerDie();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UIElements;
public class MonsterController : MonoBehaviour
{
private Transform monsterTr;
private Transform playerTr;
private NavMeshAgent agent;
private Animator animator;
private float attackDelay = 2.0f;
public enum State {
Idle,
Trace,
Attack,
Die
}
public State state = State.Idle;
public float tranceDist = 10.0f;
public float attckDist = 2.0f;
public bool isDie = false;
public int EnemyHP = 3;
private GameObject bloodEffect;
private readonly int hashPlayerDie = Animator.StringToHash("PlayerDie");
private readonly int hashSpeed = Animator.StringToHash("Speed");
private void OnEnable()
{
PlayerController.OnPlayerDie += this.OnPlayerDie;
}
private void OnDisable()
{
PlayerController.OnPlayerDie -= this.OnPlayerDie;
}
void Start()
{
animator = GetComponent<Animator>();
monsterTr = GetComponent<Transform>();
playerTr = GameObject.FindWithTag("Player").GetComponent<Transform>();
agent = GetComponent<NavMeshAgent>();
bloodEffect = Resources.Load<GameObject>("BloodSprayEffect");
Debug.Log(bloodEffect + "로드완료");
StartCoroutine(CheckMonsterState());
}
IEnumerator CheckMonsterState()
{
while (!isDie)
{
yield return new WaitForSeconds(0.3f);
float distance = Vector3.Distance(playerTr.position, monsterTr.position);
if (distance <= attckDist && state != State.Attack)
{
LookAtPlayer();
state = State.Attack;
animator.SetInteger("state", (int)state);
agent.SetDestination(transform.position);
yield return new WaitForSeconds(attackDelay); // 공격 후 지정한 시간만큼 대기
state = State.Idle; // 대기 시간 후 Idle 상태로 변경
animator.SetInteger("state", (int)state);
}
else if (distance <= tranceDist)
{
state = State.Trace;
animator.SetInteger("state", (int)state);
LookAtPlayer();
agent.destination = playerTr.position;
}
else
{
state = State.Idle;
animator.SetInteger("state", (int)state);
}
}
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("BULLET"))
{
Destroy(other.gameObject);
// Blood effect logic
Vector3 pos = other.ClosestPointOnBounds(transform.position);
Quaternion rot = Quaternion.LookRotation(-other.transform.forward); // 방향을 역으로 설정
ShowBloodEffect(pos, rot);
EnemyHP--;
// 넉백 효과 추가
Vector3 knockbackDirection = (monsterTr.position - playerTr.position).normalized; // 플레이어와의 반대 방향 계산
float knockbackDistance = 2.0f; // 넉백 거리
Vector3 knockbackPosition = monsterTr.position + knockbackDirection * knockbackDistance;
this.transform.position = knockbackPosition; // 넉백 위치로 이동
if (EnemyHP <= 0)
{
isDie = true;
state = State.Die;
animator.SetInteger("state", (int)state);
Collider enemyCollider = GetComponent<Collider>();
if (enemyCollider != null)
{
Destroy(enemyCollider);
}
Destroy(this.gameObject,2f);
// NavMeshAgent 비활성화
agent.enabled = false;
// 코루틴 정지
StopAllCoroutines();
}
}
}
void ShowBloodEffect(Vector3 pos, Quaternion rot)
{
GameObject blood = Instantiate<GameObject>(bloodEffect, pos, rot, monsterTr);
Destroy(blood,1f);
}
private void LookAtPlayer()
{
Vector3 direction = (playerTr.position - transform.position).normalized; // 플레이어 방향 계산
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z)); // 회전값
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f); //회전
}
private void OnDrawGizmos()
{
if(state == State.Trace)
{
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(transform.position, tranceDist);
}
if(state == State.Attack)
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, attckDist);
}
}
void OnPlayerDie()
{
StopAllCoroutines();
agent.isStopped = true;
animator.SetFloat(hashSpeed, Random.Range(0.8f, 1.2f));
animator.SetTrigger(hashPlayerDie);
}
}
반응형
'KDT > 유니티 심화' 카테고리의 다른 글
[SpaceShooter] 오브젝트 풀링 연습 (0) | 2023.08.28 |
---|---|
[SpaceShooter] Player 피격시 체력 바 감소(UI) 구현 (0) | 2023.08.25 |
[SpaceShooter] Monster 공격과 피격 구현 (0) | 2023.08.24 |
[SpaceShooter] Player를 따라오는 Monster 구현 + NavMeshAgent (0) | 2023.08.23 |
[SpaceShooter] 가장 가까운 적에게 총 발사하기 (0) | 2023.08.22 |