using System;
using System.Collections;
using System.Threading;
using UnityEngine;
using UnityEngine.AI;

public class MonsterController : MonoBehaviour
{
    public float detectRange = 5.0f; // 플레이어 탐지 범위
    public float attackRange = 1.0f; // 공격 범위
    public float wanderRadius = 10f;  // 무작위 이동 범위  
    private Animator animator; 
    private GameObject player; // 플레이어 오브젝트
    private bool isAttacking; // 공격 중인지 여부
    private NavMeshAgent agent;  
    private float timeToChangeDirection = 0; // 방향을 변경할 시간
    [SerializeField]
    private GameObject hitFxPrefab;
    public Action onHit;

    private bool isBeingDamaged = false;

    private enum MonsterState
    {
        Idle,
        Damaged,
        run
    }
    private MonsterState currentState = MonsterState.Idle;
    private void Start()
    {
        animator = GetComponent<Animator>();
        player = GameObject.FindWithTag("Player");
        agent = GetComponent<NavMeshAgent>();
        StartCoroutine(MonsterBehavior());
    }

    private IEnumerator TransitionToIdle()
    {
        // "Damaged"는 피격 애니메이션의 이름입니다. Animator에서 사용하는 정확한 이름을 입력하십시오.
        yield return StartCoroutine(WaitForAnimation("GetHit", () =>
        {
            this.animator.SetInteger("state", 0);
            isBeingDamaged = false;
        }));
    }
    //private IEnumerator MonsterBehavior()
    //{

    //        float distanceToPlayer = Vector3.Distance(player.transform.position, transform.position);

    //        //if (distanceToPlayer <= attackRange)     //monster state= 0: Idle, 1: Damaged, 2: run
    //        //{
    //        //    isAttacking = true;
    //        //    //animator.SetInteger("state", 1); // attack 애니메이션 재생
    //        //    LookAtPlayer(); // 플레이어를 바라봄
    //        //    agent.SetDestination(transform.position); // 몬스터는 현재 위치에 머무름
    //        //}

    //        //else 
    //        if (distanceToPlayer <= detectRange)
    //        {
    //            animator.SetInteger("state", 0);
    //            LookAtPlayer();
    //            //agent.SetDestination(player.transform.position);
    //            agent.SetDestination(transform.position);
    //        }

    //        //else
    //        //{
    //        //    animator.SetInteger("state", 2);
    //        //    if (timeToChangeDirection <= 0)
    //        //    {
    //        //        MoveRandomly();
    //        //        timeToChangeDirection = UnityEngine.Random.Range(1, 5);
    //        //        yield return new WaitForSeconds(timeToChangeDirection);
    //        //    }
    //        //    timeToChangeDirection -= Time.deltaTime;
    //        //}
    //        yield return null;

    //}
    private IEnumerator MonsterBehavior()
    {
        while (true)
        {
            if (!isBeingDamaged)
            {
                float distanceToPlayer = Vector3.Distance(player.transform.position, transform.position);

                if (distanceToPlayer <= detectRange)
                {
                    animator.SetInteger("state", 0);
                    LookAtPlayer();
                    agent.SetDestination(transform.position);
                }
            }
            yield return null;
        }
    }

    public void OnDamaged() 
    {
        isBeingDamaged = true;
        currentState = MonsterState.Damaged;
        animator.SetInteger("state", 1);
        if (hitFxPrefab)
        {
            Instantiate(hitFxPrefab, transform.position + new Vector3(0, 1f, 0), Quaternion.identity);
        }
        StartCoroutine(TransitionToIdle());
    }

    private void LookAtPlayer()
    {
        Vector3 direction = (player.transform.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 MoveRandomly()
    {
        Vector3 newPos = GetRandomPosition(); // 새로운 위치를 무작위로 가져옴
        agent.SetDestination(newPos); // 새 위치로 이동을 시작
    }

    private Vector3 GetRandomPosition()
    {
        Vector3 randomDirection = UnityEngine.Random.insideUnitSphere * wanderRadius; // 무작위 방향 계산
        randomDirection += transform.position; // 현재 위치에 더함
        NavMeshHit hit;
        NavMesh.SamplePosition(randomDirection, out hit, wanderRadius, 1); // 무작위 위치 계산
        return hit.position; // 무작위 위치를 반환
    }
    public void HitDamage()
    {
        Debug.Log("피해 애니메이션을 실행합니다.");
        if (this.onHit != null)
            this.onHit();
        this.animator.SetInteger("state", 1);

        //StartCoroutine(TransitionToIdle());
    }

    private IEnumerator WaitForAnimation(string animationName, Action callback)
    {
        bool isAnimationRunning = true;

        // 현재 애니메이터의 상태를 얻습니다.
        while (isAnimationRunning)
        {
            if (animator.GetCurrentAnimatorStateInfo(0).IsName(animationName))
            {
                if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1.0f)
                {
                    isAnimationRunning = false;
                }
            }
            yield return null;
        }

        callback();
    }

}
using System;
using System.Collections;
using UnityEngine;

public class DogController : MonoBehaviour
{
    public float speed = 5.0f; // 캐릭터의 이동 속도
    public float attackRange = 2.0f; // 캐릭터의 공격 범위
    private Animator animator;
    private Camera camera;
    private bool isMove; // 캐릭터가 움직이는지 여부
    private bool isAttacking; // 캐릭터가 공격 중인지 여부
    private Vector3 destination; // 캐릭터의 목적지
    private Transform monsterTarget; // 공격 대상인 몬스터

    public GameObject groundMarkerPrefab; // 지상 마커 프리팹
    public GameObject monsterMarkerPrefab; // 몬스터 마커 프리팹
    private GameObject currentMarker; // 현재 생성된 마커
    public float markerHeight = 1.5f; // 마커 높이

    private MonsterController monster;

    private bool isParticlePlaying = false;


    [SerializeField]
    private GameObject hitFxPrefab;

    private void Awake()
    {
        camera = Camera.main; // 메인 카메라
    }

    private void Start()
    {
        animator = GetComponent<Animator>();
        StartCoroutine(DogBehavior());


       
    }



    private IEnumerator DogBehavior()
    {
        while (true)
        {
            if (Input.GetMouseButton(1))
            {
                RaycastHit hit;
                // 마우스 위치에서 카메라 방향으로 레이캐스트를 발사
                if (Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out hit))
                {
                    // 기존의 마커가 있다면 삭제
                    if (currentMarker != null)
                    {
                        Destroy(currentMarker);
                    }

                    // 몬스터에게 레이가 닿았다면
                    if (hit.collider.tag == "Monster")
                    {
                        Debug.Log("hit Monaster to ray!");
                        monsterTarget = hit.transform;


                        SetDestination(hit.point); // 몬스터 위치로 목적지 설정
                                                   // 몬스터 마커 생성
                        currentMarker = Instantiate(monsterMarkerPrefab);
                        // 마커를 몬스터 위에 위치시킴
                        currentMarker.transform.position = monsterTarget.position + Vector3.up
                            * (monsterTarget.GetComponent<Collider>().bounds.extents.y
                            + currentMarker.transform.localScale.y + markerHeight);

                        // onHit 설정
                        monster = monsterTarget.GetComponent<MonsterController>();
                        Debug.Log(monster.gameObject.name);


                        //monster.onHit = () => {
                        //    Debug.Log("이펙트 생성");

                        //    Vector3 offset = new Vector3(0, 0.5f, 0);
                        //    Vector3 tpos = monster.transform.position + offset;

                        //    Debug.LogFormat("생성위치: {0}", tpos);
                        //    // 프리팹 인스턴스(복사본) 생성 
                        //    GameObject fxGo = Instantiate(this.hitFxPrefab);
                        //    // 위치 설정 
                        //    fxGo.transform.position = tpos;
                        //    // 파티클 실행 
                        //    fxGo.GetComponent<ParticleSystem>().Play();
                        //};

                    }
                    else // 지면에 레이가 닿았다면
                    {
                        monsterTarget = null;
                        SetDestination(hit.point); // 지면의 위치로 목적지 설정
                                                   // 지면 마커 생성
                        currentMarker = Instantiate(groundMarkerPrefab);
                        // 마커를 지면 위에 위치시킴
                        currentMarker.transform.position = hit.point + Vector3.up
                            * (currentMarker.transform.localScale.y + markerHeight);
                    }
                }
            }

            // 공격 대상이 있다면
            if (monsterTarget != null)
            {
                // 몬스터의 위치로 목적지 재설정
                SetDestination(monsterTarget.position);
                // 마커를 몬스터의 위치로 재설정
                currentMarker.transform.position = monsterTarget.position + Vector3.up
                    * (monsterTarget.GetComponent<Collider>().bounds.extents.y
                    + currentMarker.transform.localScale.y + markerHeight);
            }

            Move(); // 움직이는 함수 호출

            yield return null;
        }
    }

    private void SetDestination(Vector3 dest)  // player state= 0:idle, 1:run,  2: attack
    {
        // 목적지를 설정하고, run 상태로 설정. 공격은 false로
        destination = new Vector3(dest.x, transform.position.y, dest.z);
        isMove = true;
        isAttacking = false;
        animator.SetInteger("state", 1);
    }
    public void TriggerAttack()
    {
        Debug.Log("TriggerAttack Start!");
        if (monsterTarget != null)
        {
            MonsterController monsterController = monsterTarget.GetComponent<MonsterController>();
            Debug.Log(monsterController);
            Debug.Log("monsterController Attached!");
            if (monsterController != null)
            {
                Debug.Log("monsterCOntroller != null!");
                monsterController.OnDamaged();
            }
        }
    }
    private void Move()
    {
        // run 상태일 때
        if (isMove)
        {
            // 공격 대상이 있고 공격 범위 안에 있다면
            if (monsterTarget != null && Vector3.Distance(monsterTarget.position, transform.position) <= attackRange) 
            {
                
                // 이동 중단
                isMove = false;
                // attack 시작
                isAttacking = true;
                animator.SetInteger("state", 2);
                //monster.HitDamage();
                return;
            }
            else if (Vector3.Distance(destination, transform.position) <= 0.1f)
            {
                // 목적지에 도착
                isMove = false;
                animator.SetInteger("state", 0);
                return;
            }

            // 목적지 방향으로 이동
            Vector3 dir = (destination - transform.position).normalized;
            transform.forward = dir;
            transform.position += dir * Time.deltaTime * speed;
        }
    }
}

+ Recent posts