본문 바로가기
KDT/유니티 심화

23/08/27 [주말과제] HeroShooter Stage1 미완

by 잰쟁 2023. 8. 27.
728x90

Player

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

public class Player : MonoBehaviour
{
    private Transform playerTrans;
    public float moveSpeed = 5f;
    private Animator anim;
    public float turnSpeed = 80f;
    private Rigidbody rBody;
    [SerializeField]
    private float radius = 1.0f;
    [SerializeField]
    private float rayOffsetY = 0.5f;  //Ray 오프셋
    [SerializeField]
    private Monster target;

    //Stage2의 몬스터 2마리
    private Collider[] monsterColl = new Collider[2];

    void Start()
    {
        this.playerTrans = this.GetComponent<Transform>();
        this.anim = this.GetComponent<Animator>();
        this.rBody = this.GetComponent<Rigidbody>();
    }

    //몬스터 게임오브젝트를 사전에 넣어서 관리
    Dictionary<GameObject, float> dic = new Dictionary<GameObject, float>();

    void Update()
    {
        this.SearchMonster();
    }    

    //이동 메서드
    public void Move(Vector3 dir)
    {
        //애니메이션
        this.anim.SetInteger("State", 1);
        //회전하기
        float angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
        this.playerTrans.localRotation = Quaternion.AngleAxis(angle, Vector3.up);
        //이동하기
        this.playerTrans.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
    }

    //정지 메서드
    public void Idle()
    {
        this.anim.SetInteger("State", 0);
    }

    //거리를 구해서 몬스터 검색하는 메서드
    public void SearchMonster()
    {
        //layMask를 이용
        Collider[] targetCols = Physics.OverlapSphere(this.playerTrans.position, this.radius, 1 << LayerMask.NameToLayer("Monster"));
        this.dic.Clear();  //사전에 있는 정보 초기화

        //for문을 돌며 GameObject를 키값으로 거리 정보를 dic에 저장
        for(int i = 0; i < targetCols.Length; i++)
        {
            Collider col = targetCols[i];
            //거리 구하기
            float distance = Vector3.Distance(col.transform.position, this.playerTrans.position);
            //거리 정보를 dic에 저장
            this.dic.Add(col.gameObject, distance);
        }

        //공격 사거리 안에 몬스터가 있다면
        if(this.dic.Count > 0)
        {
            //가장 작은 값(가까운 거리)을 저장
            float nearestDistance = this.dic.Values.Min();
            //
            GameObject target = this.dic.FirstOrDefault(x => x.Value == nearestDistance).Key;
            //player로부터 타겟의 방향
            Vector3 dir = target.transform.position - this.playerTrans.position;
            //Ray 생성
            Ray ray = new Ray(this.transform.position + (Vector3.up * this.rayOffsetY), dir);
            //Ray 그리기
            Debug.DrawRay(ray.origin, ray.direction * 1000f, Color.red);

            int layerMask = 1 << LayerMask.NameToLayer("Monster") | 1 << LayerMask.NameToLayer("Wall") | 1 << LayerMask.NameToLayer("Tree");

            RaycastHit hit;
            //layMask를 이용하여 몬스터, 벽, 나무 구분하기
            if (Physics.Raycast(ray, out hit, 1000f, layerMask))
            {
                //tag가 몬스터라면
                if(hit.collider.CompareTag("Monster"))
                {
                    if(this.target != null)
                    {
                        this.target.HideIndicator();
                        //몬스터를 바라보기
                        this.playerTrans.LookAt(this.target.transform.position);
                    }
                    Monster monster = hit.collider.gameObject.GetComponent<Monster>();
                    monster.ShowIndicator();
                    this.target = monster;
                }
                else
                {
                    Monster[] monsters = GameObject.FindObjectsOfType<Monster>();
                    //몬스터 수 출력
                    Debug.Log(monsters.Count());

                    foreach(Monster monster in monsters)
                    {
                        monster.HideIndicator();
                    }
                    this.target = null;
                }
            }
        }
    }


    private void OnDrawGizmos()
    {
        Gizmos.color = Color.white;
        GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.radius);
    }
}

Monster

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

public class Monster : MonoBehaviour
{
    private Animator anim;
    [SerializeField]
    private GameObject indicator;

    // Start is called before the first frame update
    void Start()
    {
        this.anim = this.GetComponent<Animator>();
    }

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

    //indicator 숨김 메서드
    public void HideIndicator()
    {
        Debug.Log("공격 대상 아님");
        this.indicator.SetActive(false);
    }

    //indicator 출력 메서드
    public void ShowIndicator()
    {
        Debug.Log("공격 대상!");
        this.indicator.SetActive(true);
    }
}

 

흠..... Ray가 이상하게 나가는거 같다..

문제를 찾아서 다시 고쳐야할듯