using System.Collections;
using System.Linq;
using UnityEngine;
public class AutoAttack : MonoBehaviour
{
float range;
float delay = 2f;
int damage;
[SerializeField] Transform target;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
range = 4f;
StartCoroutine(StartAutoAttack());
}
// Update is called once per frame
void Update()
{
}
IEnumerator StartAutoAttack()
{
WaitForSeconds wait = new WaitForSeconds(delay);
while (true)
{
//적이 범위안에 들어올때까지 대기
yield return new WaitUntil(()=>DetectEnemy());
Attack();
yield return wait;
}
}
bool DetectEnemy()
{
int layer = LayerMask.NameToLayer("Monster");
int targetLayer = 1 << layer;
Collider2D[] coliider = Physics2D.OverlapCircleAll(transform.position, range, targetLayer);
if (coliider.Length == 0)
{
return false;
}
else
{
float min = 0;
//foreach (var col in coliider)
//{
// if (Vector2.Distance(col.transform.position, transform.position) < min)
// {
// min = Vector2.Distance(col.transform.position, transform.position);
// target = col.transform;
// }
//}
target = coliider.OrderBy(col => Vector2.Distance(col.transform.position, transform.position)).FirstOrDefault().transform;
return true;
}
}
void Attack()
{
//화살생성
GameObject arr = ObjectPoolManager.instance.GetObject("arrow");
arr.transform.position = transform.position;
Vector2 direction = target.position - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
Quaternion rotate = Quaternion.Euler(0, 0, angle);
arr.transform.rotation = rotate;
arr.GetComponent<Arrow>().SetDamage(5);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
Gizmos.DrawSphere(transform.position, range);
}
// overlap
// 1. OverlapCircle
// 1-1. OverlapCircleAll
//
// 2. OverlapBox
// 2-1. OverlapBoxAll
//
// 차이점
// 1. 반환형 -> collider
// 2. 충돌X - 검사를 함.
}
적이 범위 안에 들어오는 것을 기다림 공격 후 딜레이 wait에 2초
float delay = 2f;
IEnumerator StartAutoAttack()
{
WaitForSeconds wait = new WaitForSeconds(delay);
while (true)
{
//적이 범위안에 들어올때까지 대기
yield return new WaitUntil(()=>DetectEnemy());
Attack();
yield return wait;
}
}
범위 안에 몬스터라는 layer가 들어오면 coliider에 넣어서 제일 가까운 적을 감지.
bool DetectEnemy()
{
int layer = LayerMask.NameToLayer("Monster");
int targetLayer = 1 << layer;
Collider2D[] coliider = Physics2D.OverlapCircleAll(transform.position, range, targetLayer);
if (coliider.Length == 0)
{
return false;
}
else
{
float min = 0;
target = coliider.OrderBy(col => Vector2.Distance(col.transform.position, transform.position)).FirstOrDefault().transform;
return true;
}
}
//범위를 그려주는 기즈모
private void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
Gizmos.DrawSphere(transform.position, range);
}
화살을 오브젝트풀에서 꺼내서 위 코드에서 감지된 제일 가까운 적 target을 향해 화살 발사.
void Attack()
{
//화살생성
GameObject arr = ObjectPoolManager.instance.GetObject("arrow");
arr.transform.position = transform.position;
Vector2 direction = target.position - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
Quaternion rotate = Quaternion.Euler(0, 0, angle);
arr.transform.rotation = rotate;
arr.GetComponent<Arrow>().SetDamage(5);
}
using UnityEngine;
using UnityEngine.UI;
public class HPbar : MonoBehaviour
{
Image img;
[SerializeField] Transform target; //체력바가 붙을 대상
Vector3 offset = Vector3.up;
float gauge;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
img = GetComponent<Image>();
}
// Update is called once per frame
void Update()
{
}
private void LateUpdate()
{
if(target == null)
{
return;
}
transform.position = target.position + offset;
}
public void SetGauge(float gauge)
{
img.fillAmount = gauge;
}
public void SetTarget(Transform t)
{
target = t;
}
}

📺 "게임 화면 맨 앞에 스티커처럼 딱 붙여두기"
개념: 게임 속 카메라의 위치, 각도, 맵의 크기와 상관없이 무조건 모니터 화면 맨 앞에 UI를 띄웁니다.
특징: * 카메라가 멀어지거나 회전해도 UI는 항상 화면 정면에 고정되어 있습니다.
🎥 "카메라 렌즈 앞 일정한 거리에 띄워두기"
개념 : UI를 특정 카메라(Render Camera) 앞의 지정된 거리(Plane Distance)에 배치합니다.
특징 : Overlay처럼 화면에 고정되어 있는 것처럼 보이지만, 카메라와 UI 사이에 실제 게임 오브젝트가 끼어들 수 있습니다.
🌲 "UI를 나무나 상자 같은 하나의 게임 오브젝트로 만들기"
개념 : UI를 화면에 고정하는 것이 아니라, 게임 맵(World)의 특정 좌표에 직접 배치합니다.
특징 : * UI가 일반 캐릭터나 장애물처럼 취급되므로, 크기를 마음대로 줄여서 맵에 배치할 수 있습니다.
캐릭터 위에 체력바가 위치하도록 해주었음.
Vector3 offset = Vector3.up;
private void LateUpdate()
{
if(target == null)
{
return;
}
transform.position = target.position + offset;
}
using System.Collections;
using UnityEngine;
public enum SFXType
{
Arrow,
Die,
Attack
}
public class SoundManager : MonoBehaviour
{
public static SoundManager instance;
[SerializeField] AudioSource bgmAudioSource;
[SerializeField] AudioSource sfxAudioSource;
public AudioClip audioClip; // 배경음
public AudioClip[] soundClip; // 효과음
private void Awake()
{
if (instance == null)
{
instance = this;
}
else
{
Destroy(gameObject);
}
DontDestroyOnLoad(gameObject);
}
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
//PlayBGM();
}
// Update is called once per frame
void Update()
{
}
void PlayBGM()
{
bgmAudioSource.Play();
}
public void PlaySFX(SFXType type)
{
if((int)type > soundClip.Length)
{
return;
}
sfxAudioSource.PlayOneShot(soundClip[(int)type]);
}
IEnumerator BGMChange()
{
float vol = bgmAudioSource.volume;
float timer = 0f;
float duration = 5f;
while(vol > 0)
{
timer += Time.deltaTime;
bgmAudioSource.volume = Mathf.Lerp(vol, 0, timer / duration);
yield return null;
}
bgmAudioSource.Stop();
}
//새로운 bgm으로 바꾸고
//점점 소리를 키우면됌.
}
효과음은 soundClip에 넣어주었고 그냥 bgm은 audioclip에 넣어주었다.
그리고 각자 불륨이나 세부적인 조정사항은 위에 audio Source를 만들어서 각자 관리를 할 수 있게 해주었음.

들어있는 효과음을 사용할 수 있도록 하는 함수.
public void PlaySFX(SFXType type)
{
if((int)type > soundClip.Length)
{
return;
}
sfxAudioSource.PlayOneShot(soundClip[(int)type]);
}
//이걸 다른곳에서 불러와주면 됌.
SoundManager.instance.PlaySFX(SFXType.Arrow);
불륨이 점점 낮아지면서 bgm이 꺼지도록 하는 함수
IEnumerator BGMChange()
{
float vol = bgmAudioSource.volume;
float timer = 0f;
float duration = 5f;
while(vol > 0)
{
timer += Time.deltaTime;
bgmAudioSource.volume = Mathf.Lerp(vol, 0, timer / duration);
yield return null;
}
bgmAudioSource.Stop();
}

Add Property를 한 후에 sprite로 만들어진 이미지를 애니메이션 처럼 만들 수 있다.