유니티 기초

몬스터 클릭해서 공격

다모아 2023. 8. 8. 17:47

HeroController

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test
{
    public class HeroController : MonoBehaviour
    {
        private Vector3 targetPosition;
        private Coroutine moveRoutine;
        private Animator anim;
        public System.Action<MonsterController> onMoveComplete;
        private MonsterController target;

        private float moveSpeed = 2f;
        public float radius = 1f;
        // Start is called before the first frame update
        void Start()
        {
            this.anim = GetComponent<Animator>();
        }

        //Method Overload
        public void Move(MonsterController target)
        {
            this.target = target;
            this.targetPosition = this.target.gameObject.transform.position;
            this.anim.SetInteger("State", 1);
            if (this.moveRoutine != null)
            {
                //이미 코루틴이 실행중이다 -> 중지
                this.StopCoroutine(this.moveRoutine);
            }
            this.moveRoutine = StartCoroutine(CoMove());
        }

        public void Move(Vector3 targetPosition)
        {
            //타겟을 지움
            this.target = null;
            //이동할 목표지점을 저장
            this.targetPosition = targetPosition;
            //이동시작
            if(this.moveRoutine != null)
            {
                //이미 코루틴이 실행중이다 -> 중지
                this.StopCoroutine(this.moveRoutine);
            }
            this.moveRoutine = StartCoroutine(CoMove());
        }
        private IEnumerator CoMove()
        {
            while (true)
            {
                //로직
                //방향을 바라봄
                this.transform.LookAt(this.targetPosition);
                //이동
                this.anim.SetInteger("State", 1);
                this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
                //목표지점과 나와의 거리를 잼
                float distance = Vector3.Distance(this.transform.position, this.targetPosition);
                //distance가 0이 될 수는 없다 가까워질 때 도착한 것으로 판단하자
                
                //타겟이 있을 경우
                if(this.target != null)
                {
                    if (distance <= 1f + 1f)
                    {
                        //도착
                        break;
                    }
                }
                else
                {
                    if (distance <= 0.1f)
                    {
                        //도착
                        break;
                    }
                }
                yield return null; //다음 프레임 시작
            }
            this.anim.SetInteger("State", 0);
            this.onMoveComplete(this.target);
        }

        private void OnDrawGizmos()
        {
            Gizmos.DrawWireSphere(this.transform.position, this.radius);
        }

        public void Attack(MonsterController target)
        {
            this.anim.SetInteger("State", 2);
            this.StartCoroutine(this.CoAttack());
        }

        private IEnumerator CoAttack()
        {
            //다음 함수 시작
            //yield return null;
            yield return new WaitForSeconds(0.1f); //0.1초 이후
            //위 아래 같은거임
            //float elaspedTime = 0;
            //while (true)
            //{
            //    elaspedTime += Time.deltaTime;
            //    if (elaspedTime > 0.1f)
            //    {
            //        break;
            //    }
            //    yield return null;
            //}
            Debug.Log("<color=red>Impact!!!!!</color");

            //0.83 - 0.1
            yield return new WaitForSeconds(0.73f);

            Debug.Log("Attack애니메이션 종료");

            this.anim.SetInteger("State", 0);
        }
    }
}

 

Test_PlayerControlSceneMain

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Test;

public class Test_PlayerControlSceneMain : MonoBehaviour
{
    [SerializeField]
    private HeroController heroController;
    [SerializeField]
    private Image image;

    private float maxDistance = 100f;
    
    // Start is called before the first frame update
    void Start()
    {
        this.heroController.onMoveComplete = ((target) => { 
            Debug.LogFormat("<color=cyan>이동을 완료했습니다. : {0}</color>", target);
            //타겟이 있다면 공격 애니메이션 실행
            if (target != null)
            {
                this.heroController.Attack(target);
            }
        });
    }

    // Update is called once per frame
    void Update()
    {
        //화면을 클릭하면 클릭한 위치로 Hero가 이동
        if(Input.GetMouseButtonDown(0))
        {
            //Ray를 만든다
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 2f);

            RaycastHit hit;
            if(Physics.Raycast(ray, out hit, maxDistance))
            {
                //충돌정보가 hit변수에 담김
                Debug.LogFormat("hit.point: {0}", hit.point);
                Debug.LogFormat("hit.collider: {0}", hit.collider.tag);
                //클릭한 오브젝트가 몬스터라면
                if(hit.collider.tag == "Monster")
                {
                    //거리를 구한다.
                    float distance = Vector3.Distance(this.transform.position, hit.collider.gameObject.transform.position);

                    MonsterController monsterController = hit.collider.gameObject.GetComponent<MonsterController>();

                    //각 반지름 더한거와 비교
                    float sumRadius = this.heroController.radius + monsterController.radius;
                    Debug.LogFormat("=> {0}, {1}", distance, sumRadius);

                    //사거리 안에 들어옴
                    if(distance <= sumRadius)
                    {
                        //공격
                    }
                    //사거리 안에 안들어옴
                    else 
                    {
                        //이동
                        this.heroController.Move(monsterController);
                        //this.heroController.Move(hit.point);
                    }
                }
                else if (hit.collider.tag == "Ground")
                {
                    this.heroController.Move(hit.point);
                }


                //this.heroGo.transform.position = hit.point;

                //Hero게임오브젝트를 이동
                //this.heroController.Move(hit.point);
            }
        }
    }
}

 

MonsterController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonsterController : MonoBehaviour
{
    public float radius = 1f;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(this.transform.position, this.radius);
    }
}

'유니티 기초' 카테고리의 다른 글

SimpleRPG  (0) 2023.08.09
이펙트  (0) 2023.08.08
몬스터 클릭해서 몬스터 있는 위치로 이동  (0) 2023.08.08
코루틴  (0) 2023.08.08
로비씬, 사과, 폭탄 - 추가사항 빼고 기본 [완성]  (0) 2023.08.07