no image
프로젝트 소개 - 「현대세계 최후의 궁수」
🎮 1. 게임 소개이번 프로젝트는 '궁수의 전설(Archero)'에서 영감을 받아 제작한 탑다운 슈팅 기반의 액션 게임입니다.현대 세계를 배경으로, 마지막 남은 궁수가 되어 적들을 물리치고 스테이지를 클리어하는 것이 목표입니다.게임의 제목은 **「현대세계 최후의 궁수」**입니다.유저는 다양한 무기와 스킬을 활용하여 몬스터와 보스를 처치하고, 방을 클리어하며 점점 더 강해지는 전투를 경험할 수 있습니다.🕹️ 2. 플레이 방법이동 조작 : W, A, S, D 키로 캐릭터를 상하좌우로 움직입니다.공격 조작 : 마우스 좌클릭으로 공격합니다. 자동 발사 방식이 아니며, 직접 눌러야 발사됩니다.스킬 선택 : 방을 클리어할 때마다 3개의 스킬 중 하나를 무작위로 선택하여 강화할 수 있습니다.스테이지 진행 : 각 ..
2025.08.05
no image
Unity - Unity의 메인 카메라(Main Camera) & Projection
🎥 Unity의 메인 카메라(Main Camera)란?✅ 1. 기본 정의Unity 씬(Scene)에서 **플레이어가 보는 시점(Viewport)**을 결정하는 렌더링 카메라기본적으로 Main Camera 태그를 가진 GameObject로 자동 생성됨Camera.main 으로 쉽게 접근할 수 있음 (GameObject.FindWithTag("MainCamera")의 성능 최적화 버전)✅ 2. Camera 주요 설정속성설명Clear Flags배경을 어떻게 처리할지 결정 (Skybox, Solid Color, Depth Only, Don't Clear)Culling Mask어떤 레이어의 오브젝트만 렌더링할지 선택Projection카메라 투영 방식 (Perspective: 원근, Orthographic: 평면..
2025.08.04
no image
Unity - Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이
🧱 Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이Unity에서 동적으로 오브젝트를 생성할 때 가장 많이 사용하는 함수는 Instantiate()다.하지만 부모를 지정하는 방식, 월드 좌표 유지 여부, 그리고 스케일/포지션의 차이까지 제대로 이해하지 않으면 예기치 못한 결과가 발생할 수 있다.이번 포스트에서는 Instantiate()의 다양한 오버로드 버전과, 다음과 같은 코드 두 개의 차이점을 중심으로 정리한다:🔍 예시private void FirstSpawn(){ Instantiate(obj, transform);}private void SecondSpawn(){ GameObject newObj = Instantiate(obj); newObj.tra..
2025.07.28
no image
Unity - Invoke() vs Coroutine 비교 정리 & InvokeRepeating()
⏰ Unity Invoke() vs Coroutine 비교 정리Unity에서 일정 시간 이후에 어떤 작업을 수행하려면 보통 Invoke()나 Coroutine을 사용한다.둘 다 **시간 지연(delay)**을 다룰 수 있지만, 구조와 활용도에는 큰 차이가 있다.이 글에서는 두 방법의 차이점, 장단점, 실제 사용 예시를 함께 정리한다.🔹 1. Invoke()란?Invoke()는 지정한 시간 후에 단 한 번 특정 함수를 호출하는 Unity 내장 함수다.✅ 사용법void Start(){ Invoke("DelayedFunc", 2f); // 2초 후 DelayedFunc 실행}void DelayedFunc(){ Debug.Log("2초 후 실행됨");}🔹 2. Coroutine이란?Coroutin..
2025.07.28
no image
Unity - Unity Coroutine(코루틴)
📌 Coroutine이란?**코루틴(Coroutine)**은 Unity에서 제공하는 특별한 함수로, 작업의 흐름을 중간에 일시정지하고, 조건이 충족되면 다시 이어서 실행할 수 있다.코루틴은 IEnumerator 반환형을 가지며, StartCoroutine() 함수를 통해 실행된다.IEnumerator ExampleCoroutine(){ Debug.Log("1초 대기 전"); yield return new WaitForSeconds(1f); Debug.Log("1초 대기 후");}StartCoroutine(ExampleCoroutine());⚙️ Coroutine 실행 흐름코루틴은 Update() 함수가 끝난 뒤 실행된다.즉, 모든 Update() 함수가 호출된 이후, 코루틴이 yield..
2025.07.28
no image
Unity - Unity MonoBehaviour 생명주기 (Lifecycle) 정리
🌀 Unity MonoBehaviour 생명주기 (Lifecycle) 정리Unity는 MonoBehaviour 기반의 스크립트를 일정한 순서로 호출하며, 게임 오브젝트의 생성부터 종료까지 다양한 이벤트 함수를 실행한다. 아래는 각 단계별로 정리한 생명주기 흐름이다. 🔹 1. 초기화 (Initialization)이벤트함수설명Awake()오브젝트가 인스턴스화된 직후 호출. 스크립트 간 참조 연결에 자주 사용. Start()보다 먼저 호출됨.OnEnable()오브젝트가 활성화될 때마다 호출. 컴포넌트가 켜지거나 오브젝트가 활성화되면 호출됨.Reset()에디터에서 컴포넌트를 추가할 때 자동 호출됨. 기본값 초기화 목적.Start()스크립트가 활성화된 상태일 때, 첫 번째 프레임 전에 단 한 번 호출됨. - ..
2025.07.28
no image
Unity - Collider2D의 Layer Overrides(Include Layers, Exclude Layers) 알아보기
✍️ 본문최근 Unity에서 OnTriggerEnter2D가 도무지 작동하지 않아 시간을 꽤 허비했습니다.알고 보니 Collider2D의 "Layer Overrides" 설정이 원인이었습니다.이번 글에서는 이 기능이 무엇인지, 왜 문제가 생기는지, 어떻게 설정해야 하는지를 정리해봅니다.🧩 Layer Overrides란?Unity 2020.3부터 Collider2D에는 Layer Overrides 기능이 추가되었습니다.이는 기존의 Physics 2D → Layer Collision Matrix 설정을 무시하고,Collider 개별 객체 단위에서 충돌 대상을 지정할 수 있는 기능입니다.💡 간단히 말해, Collider 자신만의 충돌 필터를 설정할 수 있게 된 것이죠.⚙️ 구성 요소 설명항목설명Includ..
2025.07.25
no image
Unity - 2D TopDown에서 캐릭터와 무기의 회전 및 Flip 처리 정리
Unity 2D TopDown에서 캐릭터와 무기의 회전 및 Flip 처리 정리✨ 문제 배경TopDown 방식의 2D 슈팅 게임을 만들다 보면, 마우스 방향에 따라 캐릭터가 회전하고, 무기도 함께 회전하도록 구현해야 합니다.특히 무기가 캐릭터의 하위 오브젝트(WeaponPivot)로 존재하는 경우, 마우스가 왼쪽/오른쪽으로 이동할 때 캐릭터는 SpriteRenderer.flipX를 통해 반전시키고, 무기는 Y축 회전(localEulerAngles.y)과 Z축 회전(localEulerAngles.z)을 동시에 고려해야 합니다.이 글에서는 캐릭터의 Flip 처리와 무기의 회전 처리를 어떻게 해결했는지 기록합니다.🔀 캐릭터 회전 처리private void Rotate(Vector2 direction){ ..
2025.07.23
반응형

🎮 1. 게임 소개

이번 프로젝트는 '궁수의 전설(Archero)'에서 영감을 받아 제작한 탑다운 슈팅 기반의 액션 게임입니다.
현대 세계를 배경으로, 마지막 남은 궁수가 되어 적들을 물리치고 스테이지를 클리어하는 것이 목표입니다.
게임의 제목은 **「현대세계 최후의 궁수」**입니다.
유저는 다양한 무기와 스킬을 활용하여 몬스터와 보스를 처치하고, 방을 클리어하며 점점 더 강해지는 전투를 경험할 수 있습니다.


🕹️ 2. 플레이 방법

  • 이동 조작 : W, A, S, D 키로 캐릭터를 상하좌우로 움직입니다.
  • 공격 조작 : 마우스 좌클릭으로 공격합니다. 자동 발사 방식이 아니며, 직접 눌러야 발사됩니다.
  • 스킬 선택 : 방을 클리어할 때마다 3개의 스킬 중 하나를 무작위로 선택하여 강화할 수 있습니다.
  • 스테이지 진행 : 각 방을 클리어하면 자동으로 다음 방으로 이동되며, 최종 방에서는 보스가 등장합니다.

🛠 3. 사용 기술

본 프로젝트는 Unity 엔진을 기반으로 개발되었으며, 다음과 같은 기술들을 활용하였습니다:

  • Unity 2022.3.4f1 : 프로젝트 전체 구성 및 게임 구현
  • C# : 게임 로직 전반 구현
  • GitHub : 협업을 위한 형상 관리 및 버전 관리
  • ScriptableObject : 스킬 데이터 관리 및 확장성 있는 구조 구성
  • Singleton + Manager Pattern : GameManager, SoundManager 등 핵심 매니저 구조 설계
  • FSM 기반 보스 AI : 상태 전이에 따라 공격, 이동, 스킬 등을 제어
  • 랜덤 방 생성 알고리즘 : 던전 구조를 무작위로 생성하여 반복 플레이 요소 강화
  • 2D Sprite Animation : 플레이어 및 적 애니메이션 구현
  • Sound System : BGM 및 효과음 관리

✨ 4. 주요 구현 기능

  • 무작위 스킬 선택 시스템
    방을 클리어할 때마다 3개의 스킬 중 1개를 선택해 능력을 강화할 수 있으며, ScriptableObject 기반으로 유연하게 확장 가능합니다.
  • 스테이지 클리어 흐름 및 UI 연결
    플레이어가 모든 몬스터를 처치하면 스테이지가 클리어되고, 이후 보상 및 다음 스테이지로 자연스럽게 넘어가는 구조를 구현하였습니다.
  • 보스 패턴 구현
    FSM 구조를 기반으로 한 보스의 다양한 패턴 공격과 애니메이션 전환 로직을 구현하였습니다.
  • 사운드 매니저 및 효과음 시스템
    배경음과 효과음을 상황에 따라 다르게 출력하고, 중복 재생 방지 및 볼륨 설정 기능을 추가하였습니다.

🖼 5. 게임 화면

아래는 실제 게임 실행 화면 일부입니다. 플레이어 조작, 스킬 선택, 보스전, UI 구성이 포함된 장면으로, 다양한 게임 요소들이 조화를 이루도록 구현하였습니다.

  • 기본 전투 화면: 플레이어가 적을 향해 자동으로 공격하며, 일정 시간마다 보조 스킬을 사용할 수 있도록 구성하였습니다.
  • 스킬 선택 UI: 스테이지 클리어 시 3개의 스킬 중 1개를 선택하여 성장하는 방식이며, 시각적 피드백을 강화한 UI 디자인으로 몰입감을 높였습니다.
  • 보스 전투 화면: 보스의 다양한 공격 패턴이 적용되며, 체력 바 및 연출이 강화된 별도 스테이지에서 진행됩니다.
  • 게임 클리어 화면: 최종 보스를 처치하면 승리 연출과 함께 엔딩 씬으로 전환됩니다.
  • 타이틀 화면, 튜토리얼 화면 등등..

 

설명 추가 되어있는 영상

 

짧은 설명 X 영상

 


📂 6. 프로젝트 폴더 구조

📦 02. Scripts/
├── 📂Boss/ # 보스 관련 제어 스크립트
│ ├── Axe.cs # 보스 무기 충돌 감지
│ ├── BossController.cs # 보스 상태 전이 및 FSM
│ └── BossHpBar.cs # 보스 체력 UI
├── 📂Camera/
│ └── CanvasCameraSetter.cs # UI 캔버스에 메인 카메라 자동 연결
├── 📂Manager/ # 전역 시스템 관리자 클래스들
│ ├── 📂Camera/
│ │ └── CameraManager.cs
│ ├── 📂Monster/
│ │ └── MonsterSpawnManager.cs
│ ├── 📂PlayerSpawn/
│ │ └── PlayerSpawnManager.cs
│ ├── 📂Skill/
│ │ └── SkillManager.cs
│ ├── 📂Sound/
│ │ ├── PlayerSound.cs
│ │ └── SoundManager.cs
│ ├── 📂Stage/
│ │ ├── NextStageParticle.cs
│ │ └── StageManager.cs
│ ├── 📂Tutorial/
│ │ └── SkillTutorialUIManager.cs
│ ├── 📂UI/
│ │ ├── 📂Player/
│ │ │ ├── PlayerHpBar.cs
│ │ │ └── PlayerStatUI.cs
│ │ ├── 📂SettingUI/
│ │ │ └── SoundUI.cs
│ │ ├── 📂Skill/
│ │ │ └── SkillUIManager.cs
│ │ ├── 📂Tutorial/
│ │ │ └── TutorialSlotUI.cs
│ │ └── UIManager.cs
│ └── GameManager.cs # 게임 전반 흐름 관리
├── 📂Monster/ # 일반 몬스터 AI 및 전투 관련 스크립트
│ ├── Melee_Damage.cs
│ ├── MonsterFSM.cs
│ ├── MonsterHpBar.cs
│ ├── MonsterParticleControl.cs
│ ├── MonsterProjectile.cs
│ └── MonsterStat.cs
├── 📂Player/ # 플레이어 조작 및 상태 관리
│ ├── Bullet.cs
│ ├── PlayerMovement.cs
│ ├── PlayerShooting.cs
│ └── PlayerStat.cs
├── 📂ScriptableObject/ # 스킬 데이터 저장용 ScriptableObject
│ └── SkillData_ScriptableObject.cs
├── 📂Singleton/ # 제너릭 싱글톤 베이스 클래스
│ └── Singleton.cs
├── 📂Sound/ # 사운드 재생 소스
│ └── SoundSource.cs
├── 📂Stage/ # 스테이지 전환 로직
│ └── StageChanger.cs
├── 📂Test/ # 테스트 및 디버깅용
│ ├── End.cs
│ └── TimeController.cs
├── 📂UI/ # UI 관련 스크립트
│ ├── 📂Animation/
│ │ └── UIAnimationHandler.cs
│ ├── 📂Production/
│ │ └── Siren.cs
│ ├── 📂Skill/
│ │ └── SkillSlotUI.cs
│ └── 📂Title/
│ ├── StageChangeButton.cs
│ └── StateChangeButton.cs
├── 📂Utils/ # 유틸리티 스크립트
└── └── EnemyUtil.cs

 


👤 7. 개발자

이름 역할 담당 업무 요약
이재은 팀장 스킬 및 업그레이드 시스템 구현, UI 시스템 제작, 전체 프로젝트 구조 설계 및 총괄
김용민 팀원 랜덤 방 생성 로직 구현, 배경 및 사운드 전반 설정
정세윤 팀원 보스전 로직 설계 및 구현 (AI, 애니메이션 전환, 보스 연출 등)
김유경 팀원 적 AI 설계, 공격 패턴 작성 및 난이도 조정
김노아 팀원 플레이어 이동 및 공격 시스템 구현, QA 테스트 및 전반적 기능 보완

🛠 8. 트러블슈팅 (문제 해결 기록)

 

 

👤 9. 자체 평가 의견

반응형
반응형

🎥 Unity의 메인 카메라(Main Camera)란?

✅ 1. 기본 정의

  • Unity 씬(Scene)에서 **플레이어가 보는 시점(Viewport)**을 결정하는 렌더링 카메라
  • 기본적으로 Main Camera 태그를 가진 GameObject로 자동 생성됨
  • Camera.main 으로 쉽게 접근할 수 있음 (GameObject.FindWithTag("MainCamera")의 성능 최적화 버전)

✅ 2. Camera 주요 설정

속성 설명
Clear Flags 배경을 어떻게 처리할지 결정 (Skybox, Solid Color, Depth Only, Don't Clear)
Culling Mask 어떤 레이어의 오브젝트만 렌더링할지 선택
Projection 카메라 투영 방식 (Perspective: 원근, Orthographic: 평면)
Field of View 시야각 (Perspective일 때만 적용)
Clipping Planes 카메라가 렌더링할 최소/최대 거리
Depth 여러 카메라가 있을 때 그리는 순서 (높을수록 위에 그려짐)
Target Texture RenderTexture에 출력하고 싶을 때 사용 (예: 포탈, CCTV 효과)

✅ 3. 카메라 제어 예시

🎮 플레이어 따라가기

public class FollowCamera : MonoBehaviour
{
    public Transform target;
    public Vector3 offset;

    void LateUpdate()
    {
        if (target != null)
            transform.position = target.position + offset;
    }
}

🎞 카메라 흔들기 (Shake)

public IEnumerator CameraShake(float duration, float magnitude)
{
    Vector3 originalPos = transform.localPosition;

    float elapsed = 0f;
    while (elapsed < duration)
    {
        float x = Random.Range(-1f, 1f) * magnitude;
        float y = Random.Range(-1f, 1f) * magnitude;

        transform.localPosition = new Vector3(x, y, originalPos.z);
        elapsed += Time.deltaTime;
        yield return null;
    }

    transform.localPosition = originalPos;
}

✅ 4. 메인 카메라 관련 실전 예시

예시 설명
2D 게임 Orthographic 투영 사용, 플레이어를 따라다니며 흔들림 없음
3D 게임 Perspective 투영 사용, 자유 시점 회전, 줌 인/아웃
미니맵 별도 카메라 사용 + RenderTexture
포탈/거울 카메라 + RenderTexture + RawImage 사용

✅ 5. 자주 하는 실수

  • 카메라가 씬에 두 개 이상 있을 때, Camera.main은 가장 먼저 찾은 MainCamera 태그만 사용함 → 명확한 참조 권장
  • 카메라 Depth 설정 안 해서 UI용 카메라가 게임 씬을 덮어버리는 경우 발생
  • 클리핑 거리 조정 실패 → 너무 멀거나 가까운 물체가 안 보이는 경우

🧠 마무리 정리

개념 기억 포인트
Main Camera 태그 Camera.main 접근 대상
Projection 설정 2D: Orthographic / 3D: Perspective
이동 LateUpdate로 자연스럽게 따라가기
다중 카메라 Depth, Culling Mask, RenderTexture 활용
최적화 너무 많은 카메라 활성화는 성능 저하 가능

 

 

🎯 3D에서 Orthographic 카메라를 쓰면?

✅ 핵심 효과

  • **원근감(Perspective)**이 없어진다
  • 카메라와의 거리에 상관없이 모든 오브젝트가 같은 크기로 보인다
  • 멀리 있는 물체도 작아지지 않음
  • 투시 왜곡 없음 → 마치 2D처럼 보이는 3D

👀 비교 예시

항목 Perspective (원근) Orthographic (직교)
가까운 물체 크게 보임 동일하게 보임
먼 물체 작게 보임 동일하게 보임
시야각 Field of View 설정 Size로 보기 범위 설정
대표 사용 일반 3D 게임, FPS, 3인칭 등 전략 시점, 건축 시뮬, 퍼즐, 등각 뷰 게임 등
 

🎮 시각적 차이 예시

  • Perspective
    캐릭터 앞에 있는 적은 큼직하게, 멀리 있는 적은 작게 보임 → 자연스러운 현실 느낌
    예: FPS, RPG
  • Orthographic
    앞에 있는 적이든, 멀리 있는 적이든 크기가 똑같이 보임 → 깊이 구분이 없음
    예: 전통적 RTS, 스타듀밸리 같은 탑뷰, 건축 프리뷰, 에디터 툴

🧪 Unity 실습: 전환 방법

Camera.main.orthographic = true;      // 직교 투영 모드로 전환
Camera.main.orthographicSize = 5f;    // 보이는 영역 범위 조정

🧠 언제 Orthographic을 쓰면 좋을까?

쓰면 좋은 경우 이유
등각뷰 게임 (ex: 시뮬레이션, 탑뷰 퍼즐) 모든 오브젝트를 동일한 크기로 정밀하게 보여주고 싶을 때
건축/에디터 툴 정확한 위치 비교와 거리감 없는 작업이 필요할 때
2.5D 게임 3D 모델을 사용하지만 카메라 뷰는 2D처럼 고정할 때

 


✅ 요약

  • Orthographic은 원근이 없는 평면적 시점
  • 3D 씬에서도 2D처럼 연출 가능
  • 객체가 카메라에서 멀어져도 크기 변화 없음
  • 2D UI 느낌이나 등각뷰 게임에 적합

 

사실 이걸 작성하는건 이번에 궁수의 전설 모티브로 2.5D 게임을 만들었어야 했는데 어떻게해도 잘 안됐었다..그러다보니 3D 메인 카메라에서 Orhographic을 쓰면 된다고 그러길래 해봤더니..완벽했다 허허.. 새로운걸 하나 배워간다.

왼쪽은 Projection - Perspective 오른쪽은 Projection - Orhograpihc

 

반응형
반응형

🧱 Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이

Unity에서 동적으로 오브젝트를 생성할 때 가장 많이 사용하는 함수는 Instantiate()다.
하지만 부모를 지정하는 방식, 월드 좌표 유지 여부, 그리고 스케일/포지션의 차이까지 제대로 이해하지 않으면 예기치 못한 결과가 발생할 수 있다.

이번 포스트에서는 Instantiate()의 다양한 오버로드 버전과, 다음과 같은 코드 두 개의 차이점을 중심으로 정리한다:


🔍 예시

private void FirstSpawn()
{
    Instantiate(obj, transform);
}

private void SecondSpawn()
{
    GameObject newObj = Instantiate(obj);
    newObj.transform.SetParent(transform);
}

❓ 차이점은?

  • FirstSpawn()은 Instantiate 시점에 부모(transform)를 직접 지정한다.
  • SecondSpawn()은 Instantiate 후에 SetParent()로 부모를 설정한다.

⚠️ 결정적 차이: 위치와 스케일의 기준

항목 FirstSpawn SecondSpawn
부모 지정 시점 즉시 (Instantiate 내에서) 나중에 (SetParent로 나중에 지정)
로컬 위치/회전 유지 ✅ 유지됨 ❌ 월드 좌표 기준으로 설정됨
부모 스케일의 영향 ✅ 즉시 반영 ❌ SetParent 시점에 적용 방식 다름
 

즉, 동일한 결과를 원한다면 SecondSpawn 쪽에서 아래와 같이 써야 한다:

newObj.transform.SetParent(transform, false); // worldPositionStays = false

false를 전달하면 로컬 기준으로 배치되어 FirstSpawn과 동일한 결과가 됨.


🧪 Instantiate() 오버로드 총정리

Unity는 다양한 방식으로 Instantiate()를 오버로드하고 있다:

Instantiate(obj); // 기본 복제
Instantiate(obj, transform); // 부모 지정
Instantiate(obj, transform, true/false); // 부모 + 월드/로컬 기준 설정
Instantiate(obj, position, rotation); // 위치/회전 지정
Instantiate(obj, position, rotation, parent); // 위치/회전/부모 모두 지정

함수 설명
Instantiate(original) 원본 위치/회전 그대로 복제
Instantiate(original, parent) 부모 지정, 기본적으로 로컬 좌표 기준
Instantiate(original, parent, bool worldPositionStays) 부모 지정 + 월드 좌표 유지 여부 선택
Instantiate(original, pos, rot) 위치/회전 지정하여 복제
Instantiate(original, pos, rot, parent) 위치/회전/부모까지 모두 설정 가능
 

📌 worldPositionStays란?

Instantiate(obj, parent, true);  // 현재 위치 유지하며 부모만 설정 (월드 기준)
Instantiate(obj, parent, false); // 부모 기준으로 위치 재조정 (로컬 기준)

의미
true 월드 위치/회전 유지, 부모의 로컬 기준 무시
false 부모의 로컬 위치/회전 기준으로 재배치
 

🧠 정리 요약

구분 설명
Instantiate(obj, parent) 로컬 기준으로 부모 설정됨
SetParent(transform) 월드 기준 위치로 이동됨 (스케일 왜곡 주의)
SetParent(transform, false) 로컬 기준으로 부모 설정 (추천)
Instantiate(obj, pos, rot, parent) 원하는 위치/회전 + 부모까지 완벽 지정 가능
transform.localScale 영향 부모 지정 시 즉시 반영됨, 특히 SetParent() 시 의도치 않은 스케일 왜곡 주의
 

📚 참고 링크

반응형
반응형

⏰ Unity Invoke() vs Coroutine 비교 정리

Unity에서 일정 시간 이후에 어떤 작업을 수행하려면 보통 Invoke()나 Coroutine을 사용한다.
둘 다 **시간 지연(delay)**을 다룰 수 있지만, 구조와 활용도에는 큰 차이가 있다.

이 글에서는 두 방법의 차이점, 장단점, 실제 사용 예시를 함께 정리한다.


🔹 1. Invoke()란?

Invoke()는 지정한 시간 후에 단 한 번 특정 함수를 호출하는 Unity 내장 함수다.

✅ 사용법

void Start()
{
    Invoke("DelayedFunc", 2f); // 2초 후 DelayedFunc 실행
}

void DelayedFunc()
{
    Debug.Log("2초 후 실행됨");
}

🔹 2. Coroutine이란?

Coroutine은 시간의 흐름에 따라 동작을 일시정지하고 다시 재개할 수 있는 기능이다.
IEnumerator를 반환하고, yield return을 통해 흐름을 제어한다.

✅ 사용법

void Start()
{
    StartCoroutine(DelayedCoroutine());
}

IEnumerator DelayedCoroutine()
{
    yield return new WaitForSeconds(2f);
    Debug.Log("2초 후 실행됨 (코루틴)");
}

🔍 차이점 비교

항목 Invoke() Coroutine()
기본 개념 일정 시간 후 한 번 함수 호출 흐름을 일시정지하고 재개
지연 시간 제어 고정된 1회성 딜레이 반복/조건 기반 다양하게 제어 가능
정지 조건 CancelInvoke() 호출 시 StopCoroutine() 호출 시
복잡한 로직 처리 ❌ 불가능 ✅ 가능 (반복, 조건대기 등)
가독성 간단한 작업에 유리 반복 동작일 땐 더 명확함
타이밍 유연성 낮음 높음
Time.timeScale 영향 ✅ 받음 ✅ 받음 (WaitForSeconds)

🛑 Invoke 정지 예시

▶ 전체 코드

using UnityEngine;

public class InvokeStopExample : MonoBehaviour
{
    void Start()
    {
        // 5초 후에 GameOver()를 실행하려고 예약
        Invoke("GameOver", 5f);

        // 2초 뒤에 취소
        Invoke("CancelGameOver", 2f);
    }

    void GameOver()
    {
        Debug.Log("🟥 Game Over!");
    }

    void CancelGameOver()
    {
        Debug.Log("🟨 Game Over 예약 취소");
        CancelInvoke("GameOver");
    }
}

📝 요약

  • Invoke("GameOver", 5f)로 예약 
  • 2초 후 CancelInvoke("GameOver")로 중단
  • 결국 GameOver()는 실행되지 않음

🛑 Coroutine 정지 예시

▶ 전체 코드

using UnityEngine;
using System.Collections;

public class CoroutineStopExample : MonoBehaviour
{
    private Coroutine attackRoutine;

    void Start()
    {
        attackRoutine = StartCoroutine(DelayedAttack());
        Invoke("StopAttack", 2f); // 2초 후 코루틴 중단
    }

    IEnumerator DelayedAttack()
    {
        Debug.Log("🟢 공격 준비...");
        yield return new WaitForSeconds(5f); // 5초 대기
        Debug.Log("🔴 공격 실행!");
    }

    void StopAttack()
    {
        if (attackRoutine != null)
        {
            StopCoroutine(attackRoutine);
            Debug.Log("🟨 공격 중단됨");
        }
    }
}

 

📝 요약

  • 5초 후 공격을 하려는 코루틴 실행
  • 2초 후 StopCoroutine()으로 중단
  • 결국 🔴 공격 실행!은 출력되지 않음

✅ 핵심 요약

항목 정지 방법
Invoke CancelInvoke("함수이름")
Coroutine StopCoroutine(코루틴변수) 또는 StopAllCoroutines()
 
오.. 지금 처음 알게된게 코루틴도 변수처럼 쓸수있는걸 처음 알았다...

🧪 예시 비교

🎯 예: 3초 후 공격 애니메이션 시작

✅ Invoke 방식

void Start()
{
    Invoke("StartAttack", 3f);
}

void StartAttack()
{
    animator.SetTrigger("Attack");
}

✅ Coroutine 방식

IEnumerator StartAttackCoroutine()
{
    yield return new WaitForSeconds(3f);
    animator.SetTrigger("Attack");
}

void Start()
{
    StartCoroutine(StartAttackCoroutine());
}

✅ 언제 어떤 걸 써야 할까?

상황 추천방식
단순하게 일정 시간 후 함수 실행 Invoke()
반복/조건 기반 대기 필요 Coroutine
시간 흐름에 따라 여러 동작을 연결해야 할 때 Coroutine
가독성이 중요한 짧은 로직 Invoke()
 

🧠 Tip: InvokeRepeating()도 있다!

InvokeRepeating()을 사용하면 일정 시간 간격으로 반복 실행도 가능하다.

InvokeRepeating("SpawnEnemy", 1f, 5f); // 1초 후부터 5초 간격으로 반복 실행

이 역시 코루틴의 while(true) + WaitForSeconds()로 대체 가능하지만, 매우 간단할 때는 편리하다.


🏁 결론

한 줄 요약
간단한 타이머 → Invoke() / 유연한 시간 흐름 제어 → Coroutine
 

Invoke()는 빠르고 간단하지만 제어력이 낮고, Coroutine은 더 복잡하지만 강력하다.
상황에 따라 적절히 선택하면 효율적인 Unity 개발이 가능하다.

 

🔁 Unity InvokeRepeating() 간단 정리

✅ 개념

InvokeRepeating()은 지정한 시간 후부터 일정 간격으로 함수를 반복 실행하는 Unity 내장 함수다.
Update()나 Coroutine 없이도 정기적인 타이머 기반 로직을 구현할 수 있다.


🧪 사용 예시

using UnityEngine;

public class RepeatExample : MonoBehaviour
{
    void Start()
    {
        // 2초 후부터 시작해서, 1초마다 Attack() 실행
        InvokeRepeating("Attack", 2f, 1f);
    }

    void Attack()
    {
        Debug.Log("🔥 공격 실행!");
    }
}

 


🛑 반복 중단

 
void StopAttack()
{
    CancelInvoke("Attack");
}

📌 요약 표

항목 설명
사용 함수 InvokeRepeating("함수이름", 지연시간, 반복간격)
중지 방법 CancelInvoke("함수이름") 또는 CancelInvoke()
실행 조건 MonoBehaviour가 활성화된 상태여야 실행됨
장점 매우 간단한 반복 호출에 적합
단점 복잡한 흐름 제어나 조건 분기에는 불리
 

✅ 언제 사용하면 좋을까?

사용 상황 적합 여부
단순한 반복 로직 (ex. 1초마다 이펙트 생성) 👍 매우 적합
조건에 따라 반복 중단/재개 👍 사용 가능 (with CancelInvoke)
복잡한 흐름 제어가 필요한 경우 ❌ Coroutine이 더 적합
 

🏁 결론

InvokeRepeating()은 초간단 반복 타이머를 구현할 때 매우 유용한 도구다.
단, 조건 제어나 흐름 조절이 필요하면 Coroutine으로 전환하는 것이 좋다.

 

원래 3개는 다 알고있었지만 쓰기만하고 잘 알지는 못했었다. 이번 기회로 더 잘 사용하고 언제 사용할지에대해 알게된거같다!! 실제로 많이 써봐야지..그래야 실력이 늘지 ㅠㅜ

반응형
반응형

📌 Coroutine이란?

**코루틴(Coroutine)**은 Unity에서 제공하는 특별한 함수로, 작업의 흐름을 중간에 일시정지하고, 조건이 충족되면 다시 이어서 실행할 수 있다.

코루틴은 IEnumerator 반환형을 가지며, StartCoroutine() 함수를 통해 실행된다.

IEnumerator ExampleCoroutine()
{
    Debug.Log("1초 대기 전");
    yield return new WaitForSeconds(1f);
    Debug.Log("1초 대기 후");
}
StartCoroutine(ExampleCoroutine());

⚙️ Coroutine 실행 흐름

코루틴은 Update() 함수가 끝난 뒤 실행된다.
즉, 모든 Update() 함수가 호출된 이후, 코루틴이 yield return한 지점부터 재개된다.


⏱️ 다양한 YieldInstruction 종류

YieldInstruction 설명
yield return null 다음 프레임까지 대기 후 이어서 실행
yield return new WaitForSeconds(x) x초 후에 이어서 실행
yield return new WaitForFixedUpdate() 모든 FixedUpdate() 이후에 실행됨
yield return new WaitUntil(() => condition) 주어진 조건이 true가 될 때까지 대기
yield return new WaitWhile(() => condition) 주어진 조건이 false가 될 때까지 대기
yield return www WWW 요청(웹 요청)이 완료될 때까지 대기 (UnityWebRequest 권장)
yield return StartCoroutine(Other()) 다른 코루틴이 완료될 때까지 대기
 

🔁 Coroutine 중단 및 종료

  • 중단: StopCoroutine("함수이름"), StopCoroutine(코루틴변수)
  • 모든 코루틴 종료: StopAllCoroutines()
Coroutine myRoutine;

void Start()
{
    myRoutine = StartCoroutine(MyCo());
}

void StopIt()
{
    StopCoroutine(myRoutine);
}

 

여기서 주의할점은 코루틴을 변수로 사용하지 않는다면 StopCoroutine을해도 멈추지 않는다 왜냐하면 다른 인스턴스를 참조하기 때문이다!!


✅ 언제 Coroutine을 사용해야 할까?

사용 사례설명
연출 처리 화면 전환, 효과 타이밍, 대기 후 실행 등
시간 기반 반복 일정 시간 간격으로 동작 반복 (예: 총알 발사 쿨타임)
조건 대기 어떤 조건을 만족할 때까지 기다리는 처리
비동기 작업 웹 요청, 파일 로딩 등 완료까지 시간이 걸리는 작업
 

🧠 주의할 점

  • yield return new WaitForSeconds()는 Time.timeScale의 영향을 받는다. (0이면 멈춤)
  • MonoBehaviour가 비활성화되면 코루틴도 멈춘다.
  • 코루틴 내에서 무한 루프를 만들면 게임이 멈출 수 있다.

🧪 예시: 간단한 반복 공격

IEnumerator AutoAttack()
{
    while (true)
    {
        Attack();
        yield return new WaitForSeconds(1f); // 1초마다 공격
    }
}

🏁 마무리

코루틴은 Unity 개발에서 시간을 다루는 가장 강력한 도구 중 하나이다.
처음엔 Update()보다 복잡하게 느껴질 수 있지만, 익숙해지면 타이밍 제어, 연출 구현, 대기 처리에 매우 유용하다.

 

 

흠..원래 개발할때 코루틴을 많이 썼었는데 인보크도 많이 사용하는 듯 하다 인보크와 코루틴 비교하는 글도 한번 작성해 봐야겠다.

반응형
반응형

🌀 Unity MonoBehaviour 생명주기 (Lifecycle) 정리

Unity는 MonoBehaviour 기반의 스크립트를 일정한 순서로 호출하며, 게임 오브젝트의 생성부터 종료까지 다양한 이벤트 함수를 실행한다. 아래는 각 단계별로 정리한 생명주기 흐름이다.

 

🔹 1. 초기화 (Initialization)

이벤트 함수설명
Awake() 오브젝트가 인스턴스화된 직후 호출. 스크립트 간 참조 연결에 자주 사용. Start()보다 먼저 호출됨.
OnEnable() 오브젝트가 활성화될 때마다 호출. 컴포넌트가 켜지거나 오브젝트가 활성화되면 호출됨.
Reset() 에디터에서 컴포넌트를 추가할 때 자동 호출됨. 기본값 초기화 목적.
Start() 스크립트가 활성화된 상태일 때, 첫 번째 프레임 전에 단 한 번 호출됨.

 

- Awake: 이 함수는 항상 Start 함수 전에 호출되며 프리팹이 인스턴스화 된 직후에 호출됩니다. 게임 오브젝트가 시작하는 동안 비활성 상태인 경우 Awake 함수는 활성화될 때까지 호출되지 않습니다.


- OnEnable: (오브젝트가 활성화된 경우에만): 오브젝트 활성화 직후 이 함수를 호출합니다. 레벨이 로드되거나 스크립트 컴포넌트를 포함한 게임 오브젝트가 인스턴스화될 때와 같이 MonoBehaviour를 생성할 때 이렇게 할 수 있습니다.

 

- Start: 스크립트 인스턴스가 활성화된 경우에만 첫 번째 프레임 업데이트 전에 호출됩니다.


🔹 2. 물리 업데이트 (Physics)

이벤트 함수설명
FixedUpdate() 일정 시간 간격으로 호출되는 물리 업데이트. Rigidbody 물리 계산 시 여기에 구현.
OnTriggerEnter/Stay/Exit() 트리거 충돌 감지 이벤트
OnCollisionEnter/Stay/Exit() 일반 충돌 감지 이벤트

 

Unity - Update(), FixedUpdate(), LateUpdate()

✅ Unity의 3가지 주요 루프 함수함수 이름실행 주기용도특징Update()매 프레임마다사용자 입력, 일반 로직프레임 속도에 따라 실행 빈도 달라짐 (가변)FixedUpdate()고정 시간 간격마다물리 연산 (Rigidb

dev-jen.tistory.com

- FixedUpdate: FixedUpdate 는 종종 Update 보다 더 자주 호출됩니다. 프레임 속도가 낮은 경우 프레임당 여러 번 호출될 수 있으며 프레임 속도가 높은 경우 프레임 사이에 호출되지 않을 수 있습니다. 모든 물리 계산 및 업데이트는 FixedUpdate 후 즉시 발생합니다. FixedUpdate 의 움직임 계산을 적용할 때 Time.deltaTime 만큼 값을 곱할 필요가 없습니다. FixedUpdate 가 프레임 속도와 관계없이 신뢰할 수있는 타이머에서 호출되기 때문입니다.

- Update: Update 는 프레임당 한 번 호출됩니다. 프레임 업데이트를 위한 주요 작업 함수입니다.

- LateUpdate: LateUpdate 는 Update 가 끝난 후 프레임당 한 번 호출됩니다. Update 에서 수행된 모든 계산은 LateUpdate 가 시작할 때 완료됩니다. LateUpdate 는 일반적으로 다음의 3인칭 카메라에 사용합니다. 캐릭터를 움직이고 Update 로 방향을 바꾸게 하는 경우 LateUpdate 에서 모든 카메라 움직임과 로테이션 계산을 수행할 수 있습니다. 이렇게 하면 카메라가 포지션을 추적하기 전에 캐릭터가 완전히 움직였는지 확인할 수 있습니다.

 


🔹 3. 입력 및 게임 로직 (Input & Game Logic)

이벤트 함수설명
Update() 프레임마다 한 번 호출. 게임 로직의 중심 함수
LateUpdate() Update()가 끝난 직후 호출. 주로 카메라 추적 처리 등에 사용
OnMouseDown/Up/Drag() 마우스 관련 이벤트 감지

🔹 4. 애니메이션 관련 (Animation)

이벤트 함수설명
OnAnimatorMove() 루트 모션 제어용 함수
OnAnimatorIK() IK(역운동학) 처리용 함수
StateMachineBehaviour 콜백들 OnStateEnter, OnStateExit, OnStateUpdate, OnStateIK, OnStateMove 등
내부 프로세스 State Machine Update, ProcessGraph, ProcessAnimation, WriteTransform, WriteProperties 등

🔹 5. 렌더링 전/후 처리 (Rendering)

이벤트 함수설명
OnPreCull() 카메라가 오브젝트를 컬링하기 전 호출
OnBecameVisible/Invisible() 카메라 시야에 들어오거나 나갈 때 호출
OnWillRenderObject() 오브젝트가 카메라에 의해 렌더링될 때 호출
OnPreRender() / OnPostRender() 카메라 렌더링 전/후 호출
OnRenderImage() 포스트 프로세싱에 사용
OnRenderObject() GL이나 Graphics API를 직접 호출할 때
OnDrawGizmos() 에디터에서 Gizmo를 그릴 때
OnGUI() GUI를 그릴 때. 프레임당 여러 번 호출

🔹 6. 코루틴 (Coroutine)

사용법 설명
yield return null 다음 프레임까지 대기
yield return new WaitForSeconds(x) x초간 대기
yield return new WaitForFixedUpdate() 다음 FixedUpdate 이후 실행
yield return StartCoroutine() 다른 코루틴을 완료할 때까지 대기

🔹 7. 종료 및 비활성화 (Decommissioning)

이벤트 함수 설명
OnApplicationPause() 앱이 일시정지 될 때 호출
OnApplicationQuit() 애플리케이션이 종료될 때 호출
OnDisable() 오브젝트가 비활성화될 때 호출
OnDestroy() 오브젝트가 제거되거나 씬이 종료될 때 호출됨

✅ 요약: 주요 순서 흐름

  1. Awake → OnEnable → Start
  2. FixedUpdate → Update → LateUpdate
  3. (필요 시) Trigger/Collision → Animator 관련 → Rendering → Coroutine 재개
  4. OnDisable → OnDestroy → OnApplicationQuit

 

 

원래 생명주기에 대해서는 잘 알고 있다고 생각했는데..내가 모르는 라이프사이클의 함수가 굉장히 많았다..하나씩 정리해보면서 느꼈지만 아직도 공부할게 산더미 인거같다ㅎㅎ..

반응형
반응형

✍️ 본문

최근 Unity에서 OnTriggerEnter2D가 도무지 작동하지 않아 시간을 꽤 허비했습니다.
알고 보니 Collider2D의 "Layer Overrides" 설정이 원인이었습니다.
이번 글에서는 이 기능이 무엇인지, 왜 문제가 생기는지, 어떻게 설정해야 하는지를 정리해봅니다.


🧩 Layer Overrides란?

Unity 2020.3부터 Collider2D에는 Layer Overrides 기능이 추가되었습니다.
이는 기존의 Physics 2D → Layer Collision Matrix 설정을 무시하고,
Collider 개별 객체 단위에서 충돌 대상을 지정할 수 있는 기능입니다.

💡 간단히 말해, Collider 자신만의 충돌 필터를 설정할 수 있게 된 것이죠.


⚙️ 구성 요소 설명

항목 설명
Include Layers 충돌하고자 하는 레이어만 지정합니다. 지정된 레이어만 통과 가능
Exclude Layers 충돌을 막고 싶은 레이어를 명시합니다. 포함보다 우선 순위가 높습니다

🔁 동작 우선순위

Unity에서 충돌이 발생하려면 다음 조건이 모두 만족해야 합니다:

  1. 두 Collider의 Include Layers에 서로의 레이어가 포함되어 있어야 함
  2. 두 Collider의 Exclude Layers에 서로의 레이어가 없어야 함
  3. Physics 2D의 Layer Collision Matrix에서도 서로 충돌이 가능해야 함

❗ Layer Overrides 설정이 존재하면 Collision Matrix보다 우선 적용됩니다


🔧 문제 예시와 해결

문제 상황:

  • BoxCollider2D (IsTrigger ✅)가 있음
  • Rigidbody2D 있는 플레이어가 진입하는데도 OnTriggerEnter2D() 호출 안 됨
  • 레이어 충돌 매트릭스도 제대로 설정되어 있음

원인:

Include Layers와 Exclude Layers가 둘 다 Nothing으로 되어 있어
실제로 어떤 레이어와도 충돌하지 않도록 차단되어 있었음

해결:

  • Include Layers: Everything 또는 충돌 허용할 레이어 선택
  • Exclude Layers: Nothing으로 설정

✅ 권장 설정 예시

항목
IsTrigger
Include Layers Player (또는 Everything)
Exclude Layers Nothing
플레이어 쪽 Rigidbody2D + Collider2D, 태그: "Player"
 

💡 기억할 것

  • Include Layers = Nothing이면 → 아무와도 충돌 안 함
  • Exclude Layers = Everything이면 → 모든 충돌 차단됨
  • Layer Collision Matrix가 잘 되어 있어도, Override가 있으면 무시됨

📝 마무리

Collider가 이상하게 작동하지 않을 땐, 이제 Layer Overrides도 꼭 함께 확인하세요.
특히 씬에선 잘 되는데 실제 빌드에서 안 되는 경우, 이 설정이 숨겨진 원인일 수도 있습니다...

 

후..계속 이상하게 OnTriggerEnter2D를 했는대도 아무것도 나오지않아서..당황했다 이거는 절대 안까먹을듯 하다..include, Exclude 레이어 꼭 잘 확인하자.. 덕분에 새로운거 자세히 알았네ㅎㅎ..

반응형
반응형

Unity 2D TopDown에서 캐릭터와 무기의 회전 및 Flip 처리 정리

✨ 문제 배경

TopDown 방식의 2D 슈팅 게임을 만들다 보면, 마우스 방향에 따라 캐릭터가 회전하고, 무기도 함께 회전하도록 구현해야 합니다.

특히 무기가 캐릭터의 하위 오브젝트(WeaponPivot)로 존재하는 경우, 마우스가 왼쪽/오른쪽으로 이동할 때 캐릭터는 SpriteRenderer.flipX를 통해 반전시키고, 무기는 Y축 회전(localEulerAngles.y)과 Z축 회전(localEulerAngles.z)을 동시에 고려해야 합니다.

이 글에서는 캐릭터의 Flip 처리와 무기의 회전 처리를 어떻게 해결했는지 기록합니다.


🔀 캐릭터 회전 처리

private void Rotate(Vector2 direction)
{
    float rotZ = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
    bool isLeft = Mathf.Abs(rotZ) > 90f;

    // 캐릭터의 좌우 반전 처리
    characterRenderer.flipX = isLeft;

    // 무기 회전 처리 (WeaponPivot)
    if (weaponPivot != null)
    {
        weaponPivot.localRotation = Quaternion.Euler(
            0f, // X
            isLeft ? 180f : 0f, // Y
            isLeft ? -rotZ : rotZ // Z
        );
    }

    // 무기 내부에서도 좌우 반전 처리할 수 있음 (선택)
    weaponhandler?.Rotate(isLeft);
}

✅ 핵심 포인트

  • 마우스 방향을 Atan2로 각도로 변환해 Z축 회전각을 계산합니다.
  • 각도(rotZ)가 ±90도를 넘는 경우 왼쪽으로 간주하여 flipX = true
  • 무기 피벗(WeaponPivot)은 Y축 기준 180도 회전과 Z축 회전을 조합해야 자연스럽게 반전됩니다.

🗡️ 무기 Flip 처리 예시

WeaponHandler 클래스에서 무기의 스프라이트 반전을 처리하고 싶다면 다음과 같이 작성할 수 있습니다.

public override void Rotate(bool isLeft)
{
    // 필요 시 무기 자체 SpriteRenderer 반전 (필요 없으면 생략 가능)
    weaponRenderer.flipY = isLeft;
}

단, 무기 Sprite가 여러 개거나 별도 애니메이션이 있는 경우 flipY보다 Transform.localEulerAngles 회전을 직접 조작하는 것이 더 안정적입니다.


📅 회고 및 느낀 점

오늘 하루를 무기 회전 방향 잡는 데에 대부분 썼지만, 결국 핵심은 Y축 Flip과 Z축 회전의 조합이라는 걸 깨달았습니다. 단순히 SpriteRenderer만 뒤집는 것으로는 해결되지 않으며, 부모 오브젝트인 WeaponPivot의 localRotation을 정확히 조작해야 원하는 결과를 얻을 수 있었습니다.


✨ 최종 정리 코드 (간단 버전)

float rotZ = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
bool isLeft = Mathf.Abs(rotZ) > 90f;

characterRenderer.flipX = isLeft;
weaponPivot.localRotation = Quaternion.Euler(
    0f,
    isLeft ? 180f : 0f,
    isLeft ? -rotZ : rotZ
);

이 방식은 대부분의 TopDown 슈팅에서 유용하게 사용할 수 있습니다. 이제 총도 자연스럽게 회전하고, 방향에 따라 무기와 캐릭터가 모두 올바르게 반응하게 되었습니다!

이거 만드느라..몇시간을 썼는지 모르겠네여.. 그냥 총을 구현하고 싶을 뿐이였는데 전에 쓰던 무기는 그냥 활이라서 스프라이트가 1개밖에 존재하지 않는거라 문제되지 않았지만 총은 부품 1개1개 전부 스프라이트로 되어있어서 조금 난감했었다.. 그래도.. 결국에는 해결했으니 다행이다ㅠㅜㅜ

 

 

반응형