C#과 유니티3-3

망고·2023년 12월 3일

C#과 유니티

목록 보기
6/10
post-thumbnail

[C#과 유니티, 실전 게임으로 제대로 시작하기]섹션3-3. 스터디

적군 구현하기

Enemy 객체 생성

유니티에서의 객체 생성

  • 방법1> 생성자를 통해 객체를 생성한다.
  • 방법2> 스크립트를 게임오브젝트에 부착하여 생성한다.

방법1> 생성자를 통해 객체를 생성한다.

public class Enemy : MonoBeHaviour
{
 	void start()
    {
    Enemy e = new Enemy();
    }
}

MonoBeHaviour가 붙어있으면 생성자를 통해 객체를 만들 수 없다.
-> 생성자를 통해 객체를 만들고 싶다면 MonoBeHaviour를 지워야한다.
-> MonoBeHaviour가 제거되면 유니티의 Inspector창에 스크립트를 생성할 수 없다.

방법2> 스크립트를 게임오브젝트에 부착하여 생성한다.


Enemy관련 스크립트를 설계한다.


Enemy gameObject를 생성 후 Enemy스크립트를 부착한다.

적군의 피격

피격 과정

  1. 적군과 총알이 충돌해야한다.
  2. 충돌 시 적군의 체력이 감소한다.
  3. 충돌 수 총알이 소멸된다.
  1. 적군과 총알이 충돌해야한다.
  • Collider 2D를 사용하여 서로의 충돌을 감지하도록한다.

부딪치는 물체의 게임오브젝트에 Collider 2D를 달아준다.

-> Enemy와 Bullet이 충돌기에 두 게임오브젝트에 Circle Collider 2D를 삽입하였다.(두 객체가 원형이기에 Circle을 사용하였다.)
-> 객체를 감싸는 동그란 실선은 Collider를 의미한다.

  1. 충돌 시 적군의 체력이 감소한다.
  • OnCollisionEnter2D 함수를 활용하여 콜라이더(Collider)끼리의 충돌을 스크립트로 가져온다.
    (OnCollisionEnter2D이외에 OnCollisionStay2D, OnCollisionExit2D 함수가 있다.
    OnCollisionEnter2D : 충돌이 시작할 떄 한번 호출된다.
    OnCollisionStay2D : 충돌이 되는 동안 계속 호출이 된다.
    OnCollisionExit2D : 충돌에서 빠져나갈 때 한번 호출이된다.)
  1. 충돌 수 총알이 소멸된다.
public class Enemy : MonoBehaviour
{
   private float health = 50.0f; //체력을 50으로 초기화한다.
   public float Health{
    get{return health;} //변경하면 안되는 중요한 변수들의 값이나 특별한 동작을 하여 값에 접근하거나 변경해야할 변수들은 속성을 선언하여 주는 것이 좋다.
   }
   void TakeDamage(float value){
    health -=value; //공격을 당한 데미지만큼의 값을 뺀다.
    if(health<=0)
    {
        Die();
    }
   }

   /* public float GetHealth(){
        return health; //health의 값을 반환한다.
    }*/

    void Die(){
        Destroy(gameObject); //이 Enemy스크립트가 부착되어있는 게임오브젝트를 제거한다.
    }

    void OnCollisionEnter2D(Collision2D coll){ //매개변수 coll의 타입은 Collision2D이다. 
                                               //충돌한 게임오브젝트를 가져온다. 즉, 매개변수에 충돌한 게임오브젝트가 담긴다.
        TakeDamage(10); //충돌했을 시 10만큼의 값을 뺀다.
        coll.gameObject.SetActive(false); //충돌후 객체의 활동을 flase값으로 만들어 gameview에서 사라지게 만든다.
        
    }
}

플레이어의 피격

  • Collider component: 충돌을 감지하는 용도이다.
  • RigidBody component : 충돌을 시켜줄 수 있는 물리적은 요소를 수행하는 컴포넌트이다.

Player의 스크립트

using UnityEngine;

public class Player : MonoBehaviour
{
   private float health = 100.0f; 
   public float Health{
    get{return health;} 
   }
   void TakeDamage(float value){
    health -=value; 
    if(health<=0)
    {
        Die();
    }
   }

    void Die(){
        Destroy(gameObject); 
    }

    void OnCollisionEnter2D(Collision2D coll){ 
        TakeDamage(10); 
        
    }
}

Enemy 스크립트와 유사하게 작성한다.

플레이어와 적군이 충돌하기 위해선 두 객체의 Collider와 한 객체의 RigidBody 컴포넌트가 필요하다.

Enemy 게임오브젝트에 RigidBody 컴포넌트를 생성하고 중력의 값을 0으 로 설정하였다.

해결하고 싶은 문제

문제1> 플레이어와 적군이 충돌했을 때 플레이어가 사라진다.
문제2> 적군과 총알이 충돌하였을 때 적군이 밀려간다.
문제3> 플레이어와 적군이 충돌했을 때 적군이 사라지도록한다.

문제1 해결방법

플레이어와 적군이 충돌했을 때 플레이어가 사라진다.

Enemy 스크립트 중

 void OnCollisionEnter2D(Collision2D coll){ 
        TakeDamage(10); 
        coll.gameObject.SetActive(false); //충돌한 게임오브젝트를 false값으로 만들었다.
    }

-> 때문에 플래이어와 적군이 충돌하였을 때 플레이어가 사라진다.(적군과 총알이 충돌했을 때 총알이 사라지는 경우와 동일하게 플레이어에게 적용된다.)

Tag : 유니티에서 게임오브젝트를 구분하기 위한 요소이다.
->tag를 활용하여 각 스크립트의 게임오브젝트를 구분한다.

Enemy 스크립트

void OnCollisionEnter2D(Collision2D coll){ 
      if(coll.gameObject.CompareTag("Bullet"))  {  //게임오브젝트의 태그를 비교하는 함수 CompareTag를 활용하여 Bullet 태그일 경우 if문을 실행한다.                       
        TakeDamage(10); 
        coll.gameObject.SetActive(false); 
      } 
        
    }

문제2 해결방법

적군과 총알이 충돌하였을 때 적군이 밀려간다.

방법1) Enemy 게임오브젝트의 질량을 무겁게 만든다.

-> 100의 값으로 설정했을 경우 총알을 맞았을 때 움직이지 않는 것 처럼 보인다.
-> 20의 값으로 설정하면 충돌이 일어나 살짝 움직인다.
-> 적군을 따라가서 맞춰야하는 재미를 줄 수 있다.

방법2) RigidBody 의 Body Type을 Kinematic으로 설정한다.
Dynamic : 외부에서 가해지는 다양한 물리적 힘을을 적용한다.
Kinematic : 외부에서 가해지는 물리적 힘에 반응하지 않도록한다.

-> 플레이어와 충돌하였을 때 움직이지 않는다.

문제3 해결방법

플레이어와 적군이 충돌했을 때 적군이 사라지도록한다.

Player 스크립트

상속을 활용한 적군 종류 추가

비슷한 속성을 가진 여러개의 적군을 만들기 위해 상속을 활용하면 좋다.

using UnityEngine;

public class Enemy : MonoBehaviour
{
   private float health = 50.0f; 
   public float speed = 1000f; speed의 값을 Inspector에서 자유롭게 변경할 수 있도록 public으로 전환하였다.
   public float Health{
    get{return health;} 
   }

   void TakeDamage(float value){
    health -=value; 
    if(health<=0)
    {
        Die();
    }
   }

    void Die(){
        Destroy(gameObject); 
    }

    void OnCollisionEnter2D(Collision2D coll){ 
      if(coll.gameObject.CompareTag("Bullet"))  {  
        TakeDamage(10); 
        coll.gameObject.SetActive(false);
      } 
        
    }
}
using UnityEngine;

public class Enemy1 : Enemy //Enemy class의 속성을 상속받는다.
{
    void Start(){
        Move();
    }
    
    void Move(){
        gameObject.GetComponent<Rigidbody2D>().AddForce(Vector2.left*speed); //왼쪽으로 움직이도록 한다.
    }
   
}

->Enemy를 상속받는 Enemy1의 게임오브젝트를 만든다.
같은 방식으로 Enemy2 또한 만들 수 있다.

using UnityEngine;

public class Enemy2 : Enemy 
{
    void Start(){
        Move();
    }
    
    void Move(){
        gameObject.GetComponent<Rigidbody2D>().AddForce(Vector2.right*speed); //오른쪽으로 움직이도록 한다.
    }
   
}

스폰매니저

Bullet 게임오브젝트를 프리팹하였듯이 Enemy 또한 프리팹할 수 있다.

Enemy 객체가 게임 시작할 때 생성되도록 스크립트를 구상할 것이다.

using UnityEngine;

public class SpawnManager : MonoBehaviour
{
    public GameObject EnemyPrefab1;
    public GameObject EnemyPrefab2;

    void Start(){
        SpawnEnemy(EnemyPrefab1, new Vector3(-1,2,0));
        SpawnEnemy(EnemyPrefab2, new Vector3(1,2,0));
    }
    void SpawnEnemy(GameObject prefab, Vector3 position){
        GameObject enemy = Instantiate(prefab);
        enemy.transform.position=position;
        enemy.GetComponent<Enemy>().Move();
    }
}

스크립트를 SpawnManager 게임오브젝트에 부착한다.

SpawnManager를 생성함으로 번거로움을 최소화할 수 있다.

0개의 댓글