본문 바로가기
KDT/유니티 기초

23/08/14 Test_Boss

by 잰쟁 2023. 8. 14.
728x90

Test_BossMain

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

namespace Test_Boss 
{
    
    public class Test_BossMain : MonoBehaviour
    {

        //[SerializeField]
        //private Button btnMove;
        //[SerializeField]
        //private Button btnRemove;
        [SerializeField]
        private Bull bull;
        [SerializeField]
        private Hero hero;
     
        void Start()
        {
            this.bull.onAttackComplete = () =>
            {
                this.bull.DetectAndMove();
            };

            this.bull.onMoveComplete = (nextState) =>
            {
                switch (nextState)
                {
                    case "MOVE_BACK":
                        this.bull.MoveBack();
                        break;
                    case "ATTACK":
                        this.bull.Attack();
                        break;
                    case "DETECT_AND_MOVE":
                        this.bull.DetectAndMove();
                        break;
                    case "IDLE":
                        this.bull.Idle();
                        break;
                }
            };

            this.bull.Init();
        }

        void Update()
        {
            //화면을 클릭하면 Ray를 만든다
            if (Input.GetMouseButtonDown(0))
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                Debug.DrawRay(ray.origin, ray.direction * 1000f, Color.red, 3f);

                //Ray를 사용해서 충돌체크를 한다
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, 1000f))
                {
                    //충돌을 감지해서
                    Debug.LogFormat("hit.collider: {0}", hit.collider);
                    this.hero.MoveForward(hit.point);
                }
            }
        }
    }
}

Bull

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

namespace Test_Boss 
{
    public class Bull : MonoBehaviour
    {
        public enum eState 
        { 
            Idle, DetectAndMove, Attack, MoveBack
        }
        public System.Action<string> onMoveComplete;
        public System.Action onAttackComplete;    

        [SerializeField]
        private float sight = 5f;
        [SerializeField]
        private float range = 1f;
        [SerializeField]
        private float speed = 1f;

        private Animator anim;
        private Hero target;
        private bool isWithinSight;      
        public float Range => this.range;
        private Coroutine routine;
        private Vector3 initPos;

        private eState state = eState.Idle;

         void Awake()
         {
            this.initPos = this.transform.position;
            this.anim = GetComponent<Animator>();
         }

        public void Init()
        {
            this.DetectAndMove();
        }
    

        public void DetectAndMove()
        {
            //상태 -> Idle
            this.state = eState.DetectAndMove;
            if(this.routine != null)
                StopCoroutine(this.routine);
            this.anim.SetInteger("State", 0);                    
        }

        public void Idle()
        {
            this.state = eState.Idle;
            if(this.routine != null)
                StopCoroutine(this.routine);
            this.anim.SetInteger("State", 0);
        }

        private IEnumerator CoDetectAndMove()
        {
            //매프레임마다 앞으로 이동
            while (true)
            {
                //타겟을 검색
                this.target = GameObject.FindObjectOfType<Hero>();

                //거리를 계산하고
                var distance = Vector3.Distance(this.transform.position, this.target.transform.position);
                //시야안에 있는지 확인
                if (distance <= this.sight)
                {
                    Debug.DrawLine(this.transform.position, this.target.transform.position, Color.red);
                    this.isWithinSight = true;
                }
                else
                {
                    this.target = null;
                    this.isWithinSight = false;
                }

                //시야에 들어왔다면
                if (isWithinSight == true)
                {
                    //이동 애니메이션 실행
                    this.anim.SetInteger("State", 1);

                    //대상을 바라보고
                    this.transform.LookAt(this.target.transform);
                    //이동
                    this.transform.Translate(Vector3.forward * this.speed * Time.deltaTime);
                    //거리를 계산하고
                    //var distance = Vector3.Distance(this.transform.position, this.target.transform.position);
                    //공격사거리 안에 들어오면
                    if (distance <= this.range)
                    {
                        //공격시작
                        this.onMoveComplete("ATTACK");
                        break;
                    }

                    var d = Vector3.Distance(this.transform.position, this.initPos);
                    Debug.Log(d);
                    if (d > 4f)
                    {
                        this.onMoveComplete("MOVE_BACK");
                        break;
                    }
                }
                else
                {
                    //idle 애니메이션 실행
                    this.anim.SetInteger("State", 0);
                }
                yield return null;
            }
        }
        public void Attack() 
        {
            this.state = eState.Attack;

            //루틴이 실행중이면 멈추기
            if (this.routine != null)
                StopCoroutine(this.routine);

            this.routine = this.StartCoroutine(this.CoAttack());
        }

        private IEnumerator CoAttack()
        {
            this.anim.SetInteger("State", 2);
            yield return new WaitForSeconds(1.0f);
            this.onAttackComplete();
        }

        private void OnDrawGizmos()
        {
            //시야
            Gizmos.color = Color.yellow;
            GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.sight, 20);
            //공격사거리
            Gizmos.color = Color.red;
            GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 350, this.range, 20);
        }

        public void MoveBack()
        {
            this.state = eState.MoveBack;
        }
    }
}

Hero

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

namespace Test_Boss 
{
    public class Hero : MonoBehaviour
    {
        public System.Action onMoveComplete;
        public System.Action onAttackCancel;
        private Transform targetTrans;
        private Vector3 tpos;

       
        [SerializeField]
        private float range = 1f;

        public float Range => this.range;

        void Start()
        {

        }

        void Update()
        {
            
        }

        public void MoveForward(Vector3 tpos)
        {
            this.tpos = tpos;
            //방향 바라보기
            this.transform.LookAt(this.tpos);
            //코루틴 실행
            this.StartCoroutine(this.CoMoveForward());  //문제없음
        }

        private IEnumerator CoMoveForward()
        {
            while (true)
            {
                //이동로직
                this.transform.Translate(Vector3.forward * 2f * Time.deltaTime);
                //거리구하기
                float dis = Vector3.Distance(this.tpos, this.transform.position);
                Debug.Log(dis);
                if(dis <= 0.1f)
                {
                    //도착
                    break;
                }
                yield return null;
                
            }
            Debug.Log("도착");
        }

        public void Attack(Transform targetTrans)
        {
            this.targetTrans = targetTrans;
            this.StartCoroutine(this.CoAttack());
        }

        private IEnumerator CoAttack()
        {
            yield return null;

            var dis = Vector3.Distance(this.transform.position, this.targetTrans.position);

            //시야안에 있는지 확인
            if(dis <= this.range)
            {
                //사거리안에 있다면 공격 애니메이션
            }
            else
            {
                this.onAttackCancel(); //공격 취소됨
            }
        }
        private void OnDrawGizmos()
        {
            //공격사거리
            Gizmos.color = Color.red;
            GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.range, 20);
        }
    }
}

TestMono

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

namespace Test_Boss 
{
    public class TestMono : MonoBehaviour
    {
        void Start()
        {
            
        }

        void Update()
        {
            
        }
    }
}

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

23/08/15 [광복절 과제]  (0) 2023.08.15
23/08/13 [주말과제] SimpleRPG 통합하기  (1) 2023.08.13
23/08/12 [주말과제] 복소수와 사원수  (1) 2023.08.12
23/08/11 할거  (0) 2023.08.11
23/08/10 내용 복습  (0) 2023.08.10