반응형

적을 공격하는 함수 만들기

 

//Player를 선택하고 PlayerFSM 스크립트을 수정합니다

// PlayerFSM 스크립트 수정

 

 

 

 


public class PlayerFSM : MonoBehaviour
{
  
    public enum State
    {
        Idle,
        Move,
        Attack,
        AttackWait,
        Dead
    }
    //idle 상태를 기본 상태로 지정
    public State currentState = State.Idle;

    //마우수 클릭 지점,플레이어가 이동할 목적지의 좌표를 저장할 예정
    Vector3 curTargetPos;

    GameObject curEnemy;

    public float rotAnglePerSecond = 360f; //1초에 플레이어의 방향을 360도 회전한다

    public float moveSpeed = 2f; //초당 2미터의 속도로 이동

    float attackDelay = 2f; // 공격을 한번하고 다시 공격할때 까지의 지연시간

    float attackTimer = 0f; //공격을 하고 난 뒤에 경과되는 시간을 계산하기 위한 변수

    float attackDistance = 1.5f; // 공격 거리 (적과의 거리)

    float chaseDistance = 2.5f; // 전투 중 적이 도망가면 다시 추적을 시작 하기 위한 거리



    PlayerAni myAni;


    void Start()
    {
        myAni = GetComponent<PlayerAni>();
        //  myAni.ChangeAni(PlayerAni.ANI_WALK);

        ChangeState(State.Idle, PlayerAni.ANI_IDLE);
    }

    // 적을 공격하기 위한 함수 
    public void AttackEnemy(GameObject enemy)
    {
        if (curEnemy != null && curEnemy == enemy)
        {
            return;
        }

        curEnemy = enemy;
        curTargetPos = curEnemy.transform.position;

        ChangeState(State.Move, PlayerAni.ANI_WALK);
    }


    void ChangeState(State newState, int aniNumber)
    {
        if (currentState == newState)
        {
            return;
        }

        myAni.ChangeAni(aniNumber);
        currentState = newState;
    }

    //캐릭터의 상태가 바뀌면 어떤 일이 일어날지 를 미리 정의
    void UpdateState()
    {
        switch (currentState)
        {
            case State.Idle:

                IdleState();

                break;
            case State.Move:

                MoveState();

                break;
            case State.Attack:

                AttackState();

                break;
            case State.AttackWait:

                AttackWaitState();

                break;
            case State.Dead:

                DeadState();

                break;
            default:
                break;
        }

    }

    void IdleState()
    {

    }

    void MoveState()
    {
        TurnToDestination();
        MoveToDestination();
    }

    void AttackState()
    {
        attackTimer = 0f;

        //transform.LookAt(목표지점 위치) 목표지점을 향해 오브젝트를 회전 시키는 함수
        transform.LookAt(curTargetPos);
        ChangeState(State.AttackWait, PlayerAni.ANI_ATKIDLE);
    }

    void AttackWaitState()
    {
        if (attackTimer > attackDelay)
        {
            ChangeState(State.Attack, PlayerAni.ANI_ATTACK);

        }

        attackTimer += Time.deltaTime;
    }

    void DeadState()
    {

    }

    //MoveTo(캐릭터가 이동할 목표 지점의 좌표)
   public void MoveTo(Vector3 tPos)
    {
        curEnemy = null;
        curTargetPos = tPos;
        ChangeState(State.Move, PlayerAni.ANI_WALK);
    }

    void TurnToDestination()
    {
        // Quaternion lookRotation(회전할 목표 방향) : 목표 방향은 목적지 위치에서 자신의 위치를 빼면 구함
        Quaternion lookRotation = Quaternion.LookRotation(curTargetPos - transform.position);

        //Quaternion.RotateTowards(현재의 rotation값, 최종목표rotation 값, 최대 회전각)
        transform.rotation = Quaternion.RotateTowards(transform.rotation, lookRotation, Time.deltaTime * rotAnglePerSecond);
    }

    void MoveToDestination()
    {
        //Vector3.MoveTowards(시작지점, 목표지점,최대이동거리)
        transform.position = Vector3.MoveTowards(transform.position, curTargetPos,moveSpeed * Time.deltaTime);

        if (curEnemy == null)
        {
            //플레이어의 위치와 목표지점의 위치가 같으면, 상태를 Idle 상태로 바꾸라는 명령
            if (transform.position == curTargetPos)
            {
                ChangeState(State.Idle, PlayerAni.ANI_IDLE);
            }
        }
        else if (Vector3.Distance(transform.position,curTargetPos) < attackDistance)
        {
            ChangeState(State.Attack, PlayerAni.ANI_ATTACK);
        }

  
    }
    void Update()
    {
        UpdateState();
    }
}

 

 

 

 

 

InputManager 오브젝트를 선택하고 InputManager 스크립트를 수정합니다

//InputManager 스크립트 수정

 


public class InputManager : MonoBehaviour
{

    GameObject player;
    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player");
    }

    void CheckClick()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //카메라로부터 화면사의 좌표를 관통하는 가상의 선(레이)을 생성해서 리턴해 주는 함수
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            RaycastHit hit;

            //Physics.Raycast(래이 타입 변수, out 레이캐스트 히트 타입변수) : 
            //가상의 레이저선(래이)이 충돌체와 충돌하면, true(참) 값을 리턴하면서 동시에 레이캐스트 히트 변수에 충돌 대상의 정보를 담아 주는 함수           
            if (Physics.Raycast(ray, out hit))
            {
                if (hit.collider.gameObject.name == "Terrain")
                {
                    // player.transform.position = hit.point;

                    //마우스 클릭 지점의 좌표를 플레이어가 전달받은뒤,상태를 이동상태로 바뀜
                    player.GetComponent<PlayerFSM>().MoveTo(hit.point);
                }
                else if (hit.collider.gameObject.tag == "Enemy")//마우스 클릭한 대상이 적 캐릭터인 경우
                {
                    player.GetComponent<PlayerFSM>().AttackEnemy(hit.collider.gameObject);
                }
            }
        }

    }
    // Update is called once per frame
    void Update()
    {
        CheckClick();
    }
}

 

 

 

 

게임을 실행시켜서 플레이어가 적을 공격하는지 확인합니다

0

반응형

+ Recent posts