유니티 3D게임 쿼드뷰 12

유니티 3D게임 쿼드뷰 12

Summary 클래스 상속, 보스 구현, 코루틴 사용법, localScale 조정, 모든 메쉬 색상 변경 방법, 플레이어 방향 예측 및 보스 패턴 개발에 관한 내용을 다루고 있습니다. 각 주제에 대한 코드 예시와 설명이 포함되어 있습니다.


🎥 동영상 보기

🔥 11분부터 파티클설정에대한 내용을 복습합니다

🔥 클래스 상속하는 방법

public class (스크립트이름) : (상속받을 스크립트)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

**public class BossMissile : Bullet**
{
    void Awake()
    {

    }

    void Update() 
    {

    }

}

Image

🔥 보스 바위공격 구현 Image

🔥 enum 추가하여 몬스터의 분기점 추가

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//Bullet_Enermy.cs

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

public class Bullet_Enemy : MonoBehaviour
{
    public int damage;
    public GameObject effectObj; //폭발이펙트
    public GameObject maeshObj; //미사일오브젝트 등록
    **public enum Type {Melee, Range, Boss};**
    public Type type;
    void OnCollisionEnter(Collision collision)
    {
        //몬스터 A,B 전용
        **if(type == Type.Melee)**
        {
            if(collision.gameObject.tag == "Floor")
            {
                Debug.Log("몬스터 Floor와 충돌");
            }
            else if(collision.gameObject.tag == "Wall")
            {
                Debug.Log("몬스터 Wall와 충돌");
            }
        }
        //몬스터 C 전용 (미사일에 Destroy를 사용하기 위함)
        **else if (type == Type.Range || type == Type.Boss )**
        {
            if(collision.gameObject.tag == "Floor")
            {
                Destroy(gameObject, 2);
            }
            else if(collision.gameObject.tag == "Wall")
            {
                Destroy(gameObject, 2);
            }
        }

    }

    void OnTriggerEnter(Collider other) 
    {
        //몬스터 A,B 전용
        **if(type == Type.Melee)**
        {    
            if(other.gameObject.tag == "Floor")
            {
                Debug.Log("몬스터 Floor와 충돌");
            }
            else if(other.gameObject.tag == "Wall")
            {
                Debug.Log("몬스터 Wall와 충돌");
            }
            else if(other.gameObject.tag == "Player")
            {
                Debug.Log("몬스터 플레이어와 충돌");
            }
        }
        //몬스터 C 전용 (미사일에 Destroy를 사용하기 위함)
       ** else if (type == Type.Range || type == Type.Boss )**
        {
            if(other.gameObject.tag == "Floor")
            {
                Destroy(gameObject);
            }
            else if(other.gameObject.tag == "Wall")
            {
                Destroy(gameObject);
            }
            else if(other.gameObject.tag == "Player")
            {
                Debug.Log("몬스터 미사일 플레이어와 충돌");
                maeshObj.SetActive(false);
                effectObj.SetActive(true);
                Destroy(gameObject,2f);
            }
        }

    }

}

🔥 코루틴의 while 문 안에는 yield return 딜레이를 주지 않으면 오류가 발생한다

코루틴 While문에는 꼭 yield return null; 포함

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//GainPower에서 계속 기를 모으고있음
    IEnumerator GainPower()
    {
        //isShoot이 트루가 아닐때까지 반복
        //while 문 안에는 yield return null; 딜레이를 주지 않으면 오류가 발생한다
        while(!isShoot)
        {
						yield return null;
        }
    }

🔥 transform.localScale = Vector3.one * scaleValue;

transform.localScale = Vector3.one * scaleValue;

🔥 locaslScale? Transform.localScale은 게임오브젝트의 상대적인 크기를 나타냅니다.게임오브젝트의 부모가 있을 경우 부모를 기준으로 상대적인 크기를 나타냅니다. 부모의 크기가 변경되면 자식의 크기도 변경됩니다. Transform.localScale에 Vector3를 대입하면 크기가 변경됩니다.

부모가 없을 경우에는 Transform.lossyScale과 동일합니다. 만약 부모의 localScale이 (2, 2, 2) 이고 자식의 localScale이 (1, 1, 1) 이라면 자식의 절대적인 크기는 (2, 2, 2)가 됩니다.

🔥 Vector3.one? | Vector3.forward | new Vector3 (0,0,1) | | Vector3.back | new Vector3 (0,0,-1) | | Vector3.up | new Vector3 (0,1,0) | | Vector3.down | new Vector3 (0,-1,0) | | Vector3.right | new Vector3 (1,0,0) | | Vector3.left | new Vector3 (-1,0,0) | | Vector3.one | new Vector3 (1,1,1) | | Vector3.zero | new Vector3 (0,0,0) |

🔥 몬스터도 피격당했을때 모든 메쉬 머터리얼 변경되도록 하는 방법은 Material을 사용하는것이 아니라 플레이어처럼 MeshRenderer[]로 material을 설정해준다

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//Enemy.cs

MeshRenderer[] meshs;
meshs = GetComponent**s**InChildren<MeshRenderer>();

//복수형 유의...

IEnumerator OnDamage(Vector3 reactVec, bool isGrenade)
    {
        **foreach (MeshRenderer mesh in meshs)
            mesh.material.color = Color.red;**
        reactVec = reactVec.normalized;
        reactVec += Vector3.up;
        rigid.AddForce(reactVec * 3, ForceMode.Impulse);
        yield return new WaitForSeconds(0.1f);

        if(curHealth > 0)
        {
            **foreach (MeshRenderer mesh in meshs)
                mesh.material.color = Color.white;**
        }
        else
        {
            **foreach (MeshRenderer mesh in meshs)
                mesh.material.color = Color.gray;**
            gameObject.layer = 14;
            isChase = false; //추격함수를 종료
            nav.enabled = false; //네비게이션 컴포넌트도 비활성화
            anim.SetTrigger("doDie"); //사망 애니메이션 포함
            //수류탄에 피격되었을때
            if (isGrenade)
            {
                reactVec = reactVec.normalized;
                reactVec += Vector3.up * 3;

                rigid.freezeRotation = false; //충돌해서 회전하는거 막았던거 해제
                rigid.AddForce(reactVec * 5, ForceMode.Impulse); //위치값 이동
                rigid.AddTorque(reactVec * 15, ForceMode.Impulse); //회전값
            }
            //총알에 피격되었을때
            else
            {
                reactVec = reactVec.normalized;
                reactVec += Vector3.up;
                rigid.AddForce(reactVec * 5, ForceMode.Impulse);
            }

            yield return new WaitForSeconds(1.0f);
            boxCollider.enabled = false;

            if(enemyType == Type.D)
                Destroy(gameObject, 2);
        }
    }

//foreach로 묶어버리고 mesh.material.color 로 코드 전부 변경

🔥 Boss 플레이어 방향 예측하기 1. Input.GetAxis(string name)

  • 1.0f 부터 1.0f 까지의 범위의 값을 반환한다. 즉, 부드러운 이동이 필요한 경우에 사용된다. 2. Input.GetAxisRaw(string name)

  • 1, 0, 1 세 가지 값 중 하나가 반환된다. 키보드 값을 눌렀을 때 즉시 반응해야한다면 GetAxisRaw를 사용하면 된다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//Boss.cs

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

public class Boss : Enemy
{
    public GameObject missile;
    public Transform missilePortA;
    public Transform missilePortB;

    //플레이어의 이동방향을 예측하는 변수
    Vector3 lookVec;
    Vector3 tauntVec;
    bool isLook;

    void Start()
    {
        isLook = true;
    }

    void Update()
    {
        if(isLook)
        {
            float h = Input.GetAxisRaw("Horizontal");
            float v = Input.GetAxisRaw("Vertical");
            //얼마나 예측할것인가? (5) 만큼 예측하겠다
            lookVec = new Vector3(h,0,v) * 5f;
            transform.LookAt(target.position + lookVec);
        }
    }
}

🔥 보스 패턴 개발은 Random과 Switch문을 활용합니다

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Boss.cs

IEnumerator Think()
    {
        yield return new WaitForSeconds(0.1f); //생각하는 시간 길수록 보스가 쉬워진다

        //랜덤으로 0~4값이 랜덤액션값에 들어간다
        //보스가 랜덤값에 따라 다른 패턴을 가지기 위함이다
        **int ranAction = Random.Range(0,5);
        switch (ranAction)
        {
            case 0:
                break;**
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            case 4:
                break;
        }

💬 댓글

GitHub 계정으로 로그인하여 댓글을 남겨보세요. GitHub 로그인

🔧 댓글 시스템 설정이 필요합니다

GitHub Discussions 기반 댓글 시스템을 활성화하려면:

  1. Giscus 설정 페이지에서 설정 생성
  2. GISCUS_SETUP_GUIDE.md 파일의 안내를 따라 설정 완료
  3. Repository의 Discussions 기능 활성화

Repository 관리자만 설정할 수 있습니다. 설정이 완료되면 모든 방문자가 댓글을 남길 수 있습니다.