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가 이상하게 나가는거 같다..
문제를 찾아서 다시 고쳐야할듯
'KDT > 유니티 심화' 카테고리의 다른 글
23/08/30 HeroShooter 타이틀 (비동기 씬 전환) (0) | 2023.08.30 |
---|---|
23/08/29 TestAreaMask (0) | 2023.08.29 |
23/08/24 HeroShooter 사정거리 안에 몬스터 감지 (0) | 2023.08.24 |
23/08/24 SpaceShooter 몬스터 공격 스크립트 (0) | 2023.08.24 |
23/08/23 HeroShooter 포탈 닿으면 FadeOut (0) | 2023.08.23 |