[6].1 총알 발사 제작 [6].2 적 이동 & 충돌 [6].3 적 자동 생성 [6].4 적 인공지능 |
[6].1 총알 발사 제작
🔶 PlayerFire 스크립트 생성 및 할당
- Project 창에 PlayerFire 라는 이름으로 C# 스크립트를 하나 만든다.
- Player 객체에 드래그 앤 드롭으로 붙여 준다.
🔶 총알 발사 로직
- 총의 방아쇠를 당기면 총알 공장에 전화를 하여 생산된 총알을 받아 발사 하는 흐름으로 이해 할 수 있으며 이는 총알 파을 열어 메모리에 올리는 흐름과 같다.
- 이 흐름을 처리해 주는 함수가 Instantiate 함수.
🔶 필요 속성 추가
- 총알을 생성하기 위해 총알 공장이 필요하다.
- 만들어진 총알을 발사하기 위한 위치가 필요하며 이는 총구로 속성으로 등록한다.
🖥️ PlayerFire.cs 필요속성 설정
public class PlayerFire : MonoBehaviour
{
//총알 생산할 공장
public GameObject bulletFactory;
//총구
public GameObject firePosition;
}
🔶 Bullet 프리팹 제작
- Project 창에 폴더를 하나 만들어 이름을 Prefabs 으로 변경
- 하이어라키의 Bullet 객체를 드래그 앤 드롭으로 Project 창의 Prefabs 폴더에 넣어준다.
🔶 Bullet 할당
- 씬에서 Bullet 을 제거한다.
- PlayerFire 의 Bullet Factory 속성에 Bullet 프리팹을 할당
🔶 총구 제작
- Player 객체를 선택하고 마우스 우클릭.
- Create Empty 를 선택하면 자식으로 빈 게임오브젝트가 등록이 되며, 이름을 FirePosition 으로 변경.
🔶 총구 속성 할당
- FirePosition 객체를 Player 의 PlayerFire 스크립트에 할당
🔶 사용자가 발사 버튼을 누르면
- 사용자가 왼쪽 마우스버튼 클릭을 하거나 왼쪽 Ctrl 버튼을 눌렀을때의 입력처리는 “Fire1” 에 해당한다.
- GetButtonDown 함수를 통해 입력여부를 확인하여 처리를 할 수 있다.
🖥️ PlayerFire.cs 발사 입력처리
public class PlayerFire : MonoBehaviour
{
. . . (생략) . . .
void Update()
{
//목표: 사용자가 발사 버튼을 누르면 총알을 발사하고 싶다.
//순서 : 1.사용자가 발사 버튼을 누르면
// - 만약 사용자가 발사 버튼을 누르면
if (Input.GetButtonDown("Fire1"))
{
//2.총알 공장에서 총알을 만든다.
//3.총알을 발사한다.
}
}
}
🔶 총알 공장에서 총알을 만든다
- Instantiate 함수의 인자로 총알공장 bulletFactory 를 넣어 주면 총알을 하나 생성 해준다.
🖥️ PlayerFire.cs 총알 생성
public class PlayerFire : MonoBehaviour
{
. . . (생략) . . .
void Update()
{
//목표: 사용자가 발사 버튼을 누르면 총알을 발사하고 싶다.
//순서 : 1.사용자가 발사 버튼을 누르면
// - 만약 사용자가 발사 버튼을 누르면
if (Input.GetButtonDown("Fire1"))
{
//2.총알 공장에서 총알을 만든다.
GameObject bullet = Instantiate(bulletFactory);
//3.총알을 발사한다.
}
}
}
🔶 총알을 발사한다
- 만들어진 bullet 객체에 속성으로 선언한 firePosition 총구의 위치를 할당
🖥️ PlayerFire.cs 총알 발사
public class PlayerFire : MonoBehaviour
{
. . . (생략) . . .
void Update()
{
//목표: 사용자가 발사 버튼을 누르면 총알을 발사하고 싶다.
//순서 : 1.사용자가 발사 버튼을 누르면
// - 만약 사용자가 발사 버튼을 누르면
if (Input.GetButtonDown("Fire1"))
{
//2.총알 공장에서 총알을 만든다.
GameObject bullet = Instantiate(bulletFactory);
//3.총알을 발사한다.(총알을 총구위치로 가져다 놓기)
bullet.transform.position = firePosition.transform.position;
}
}
}
[6].2 적 이동 & 충돌
🔶 Enemy 객체 생성
- 하이어라키에서 + 버튼을 눌러 그림과 같이 3D Object 의 Cube 를 하나 만들고 이름을 Enemy로 변경
🔶 Enemy 위치 설정
- 적이 생성되는 위치는 화면의 위쪽이니 Enemy의 Transform 의 Position 정보를 변경
🔶 Enemy 스크립트 할당
- Project 창에서 Scripts 폴더에 Enemy 라는 이름의 스크립트를 만든다.
- 하이어라키의 Enemy 게임오브젝트에 드래그 앤 드롭으로 붙여 준다.
🔶 이동 코드 작성
- 이동속도 속성을 선언
- 방향을 구하고 이동공식으로 코드를 구현한다.
🖥️ Enemy.cs 아래로 이동시키기
public class Enemy : MonoBehaviour
{
//필요속성 : 이동속도
public float speed = 5;
void Update()
{
// 1. 방향을 구한다.
Vector3 dir = Vector3.down;
// 2. 이동하고 싶다. 공식 P = P0 + vt
transform.position += dir * speed * Time.deltaTime;
}
}
🔶 충돌을 위한 조건
- 몸체에 해당하는 충돌체 Collder 가 필요
- 물리 역할을 담당할 Rigidbody 가 필요
🔶 충돌체
- Enemy 게임오브젝트에 붙어 있는 기본 충돌체는 BoxCollider 이다.
🔶 물체끼리 충돌하기
- Enemy 게임오브젝트에 Physics 항목의 Rigidbody를 클릭해서 컴포넌트를 추가
- 중력을 사용하지 않게 하도록 Use Gravity 속성을 꺼준다.
🔶 충돌한 물체 파괴하기
- 물체의 충돌을 감지하는 함수는 OnCollisionEnter 함수이며 이곳에서 부딪힌 객체(other) 를 제거하고 본인도 제거한다.
🖥️ Enemy.cs 충돌 처리
public class Enemy : MonoBehaviour
{
. . . (생략) . . .
// 충돌 시작
private void OnCollisionEnter(Collision other)
{
// 너죽고
Destroy(other.gameObject);
// 나죽자
Destroy(gameObject);
}
}
💡여기서... 실행 버튼을 눌러서 충돌시켰더니 씬과 하이어라키에서 그대로 사라짐 ...
[6].3 적 자동 생성
🔶 Enemy Prefab 제작 및 제거
- 하이어라키(Hierarchy)창의 Enemy 게임오브젝트를 프로젝트(Project)창의 Prefabs폴더쪽으로 드래그 앤 드롭해서 프리팹으로 만들어 준다.
- 하이어라키의 Enemy 게임오브젝트는 Del키를 눌러서 삭제
🔶 역할 정의 및 객체 생성
- 일정시간 마다 적을 만들어 내도록 하며 EnemyManager의 위치에서 적이 생성 되도록 한다.
- 하이어라키에서 [+] -> [Create Empty] 을 선택하여 빈 게임오브젝트를 하나 만들고 이름을 EnemyManager로 변경
🔶 기즈모 설정
- Scene에서 적당한 위치에 배치 후 잘 보이도록 아이콘 기즈모를 설정
- 아이콘 기즈모 설정은 EnemyManager 게임오브젝트를 클릭한 후 Inspector창의 바로 아래쪽에 있는 큐브 모양의 버튼을 누른다
🔶 EnemyManager 스크립트 생성 및 할당
- Project 창에서 Scripts 폴더에 EnemyManager 라는 이름의 스크립트를 만들어 준다.
- 하이어라키의 EnemyManager 게임오브젝트에 드래그 앤 드롭으로 붙여 준다.
🔶 목표설정
목표 | 일정시간마다 적을 생성해서 내 위치에 갖다 놓고 싶다 |
필요속성 | 일정시간, 현재시간, 적 공장 |
순서 | 1. 시간이 흐르다가 2. 만약 현재시간이 일정시간이 되면 3. 적 공장에서 적을 생성해서 내 위치에 갖다 놓고 싶다. |
🔶 필요 속성 선언
- “일정시간마다 적을 생성해서 내 위치에 갖다 놓고 싶다” 를 구현하기 위해 필요한 정보는 일정시간, 생성할 적 공장, 그리고 경과된 시간인 현재 시간으로 볼 수 있다.
- Enemy 프리팹을 EnemyManager 의 Enemy Factory 속성에 할당하여 준다.
🖥️ EnemyManager.cs 필요속성 선언
public class EnemyManager : MonoBehaviour
{
// 현재시간
float currentTime;
// 일정시간
public float createTime = 1;
// 적 공장
public GameObject enemyFactory;
}
🔶 시간이 흐르다가
- 시간을 계속 흐르게 하기위해 라이프사이클 함수 중 Update 함수에 내용을 구현한다.
- deltaTime 을 활용하여 시간을 누적시켜 완성
🖥️ EnemyManager.cs 시간이 흐르다가
public class EnemyManager : MonoBehaviour
{
. . . (생략) . . .
void Update()
{
// 1. 시간이 흐르다가
currentTime += Time.deltaTime;
}
}
🔶 만약 현재 시간이 일정시간이 되면
- 경과 시간이 생성 시간을 초과하면 문장을 구현한다.
- 단순 C# 이라는 언어로 번역하는 형태임을 인지.
🖥️ EnemyManager.cs 현재시간이 일정시간이 되면
public class EnemyManager : MonoBehaviour
{
. . . (생략) . . .
void Update()
{
// 1. 시간이 흐르다가
currentTime += Time.deltaTime;
// 2. 만약 현재시간이 일정시간이 되면
if (currentTime > createTime)
{
// 3. 적 공장에서 적을 생성해서
// 내 위치에 갖다 놓고 싶다
}
}
}
🔶 적 공장에서 적을 생성해서 내 위치에 갖다 놓고 싶다.
- 적 공장에서 적을 만들어서 내 위치에 갖다 놓는다.
🖥️ EnemyManager.cs 적 생성하기
public class EnemyManager : MonoBehaviour
{
. . . (생략) . . .
void Update()
{
// 1. 시간이 흐르다가
currentTime += Time.deltaTime;
// 2. 만약 현재시간이 일정시간이 되면
if (currentTime > createTime)
{
// 3. 적 공장에서 적을 생성해서
GameObject enemy = Instantiate(enemyFactory);
// 내 위치에 갖다 놓고 싶다.
enemy.transform.position = transform.position;
}
}
}
🔶 실행 및 문제 확인
- 그런데 하이어라키를 보면 적이 여러 개 생성되어 있는 것을 확인할 수 있다.
- 현재시간이 일정시간이 되고 난 후 계속 일정시간 보다 크기 때문에 적을 계속 생성
- 이것을 해결하기 위해 현재시간이 일정시간보다 커지면 현재시간을 0으로 초기화해야 한다.
- 경과 시간을 초기화 하여 문제 해결
🖥️ EnemyManager.cs 현재시간을 0으로 초기화
public class EnemyManager : MonoBehaviour
{
. . . (생략) . . .
void Update()
{
// 1. 시간이 흐르다가
currentTime += Time.deltaTime;
// 2. 만약 현재시간이 일정시간이 되면
if (currentTime > createTime)
{
// 3. 적 공장에서 적을 생성해서
GameObject enemy = Instantiate(enemyFactory);
// 내 위치에 갖다 놓고 싶다.
enemy.transform.position = transform.position;
// 현재시간을 0으로 초기화
currentTime = 0;
}
}
}
🔶 EnemyManager 배치
- EnemyManager 게임오브젝트를 클릭하고 키보드의 [Ctrl + D]키를 눌러 복제.
- 네 번 복제해서 다섯 개의 EnemyManager를 만들고 가로로 2유닛(미터) 간격으로 배치해준다.
🔶 목표 및 필요 속성 추가
- 목표 : 적이 생성될 때마다 다음 생성 시간을 랜덤하게 하고 싶다.
- 필요속성 : 최소, 최대시간
🖥️ EnemyManager.cs 최소시간, 최대시간 추가
public class EnemyManager : MonoBehaviour
{
// 최소시간
float minTime = 1;
// 최대시간
float maxTime = 5;
. . . (생략) . . .
}
🔶 생성시간 랜덤으로 설정
🖥️ EnemyManager.cs 생성시간을 랜덤하게 적용
public class EnemyManager : MonoBehaviour
{
. . . (생략) . . .
void Start()
{
// 태어날 때 적 생성시간을 설정하고
createTime = UnityEngine.Random.Range(minTime, maxTime);
}
void Update()
{
// 1. 시간이 흐르다가
currentTime += Time.deltaTime;
// 2. 만약 현재시간이 일정시간이 되면
if (currentTime > createTime)
{
. . . (생략) . . .
// 적을 생성한 후 적 생성시간을 다시 설정하고 싶다.
createTime = UnityEngine.Random.Range(minTime, maxTime);
}
}
}
6.[4] 적 인공지능
🔶 확률에 의한 분기처리
- Random 클래스를 이용해서 0~9중 랜덤한 하나의 수를 가져와서 그 값이 3보다 작으면 플레이어방향, 그렇지 않으면 아래방향이 되도록 조건을 만든다.
🖥️ Enemy.cs 확률에 의한 분기처리
public class Enemy : MonoBehaviour
{
. . . (생략) . . .
void Start()
{
// 0부터 9(10-1) 까지 값중에 하나를 랜덤으로 가져와서
int randValue = UnityEngine.Random.Range(0, 10);
// 만약 3보다 작으면 플레이어방향
if (randValue < 3)
{
}
// 그렇지 않으면 아래방향으로 정하고 싶다.
else
{
}
}
. . . (생략) . . .
}
🔶 방향 구하기
- 먼저 Target 인 Player 를 GameObject.Find 함수를 이용하여 찾는다.
- Vector 의 뺄샘을 활용하여 원하는 방향을 찾아낸다.
- 정규화(Normalize) 를 적용하여 Vector 의 크기를 1로 만들어 준다.
- 타겟 방향이 아닐 경우에는 아래 방향으로 정해준다.
🖥️ Enemy.cs 방향 구하기
public class Enemy : MonoBehaviour
{
. . . (생략) . . .
void Start()
{
Vector3 dir;
// 0부터 9(10-1) 까지 값중에 하나를 랜덤으로 가져와서
int randValue = UnityEngine.Random.Range(0, 10);
// 만약 3보다 작으면 플레이어방향
if (randValue < 3)
{
// 플레이어를 찾아서 target으로 하고싶다.
GameObject target = GameObject.Find("Player");
// 방향을 구하고싶다. target - me
dir = target.transform.position - transform.position;
// 방향의 크기를 1로 하고 싶다.
dir.Normalize();
}
// 그렇지 않으면 아래방향으로 정하고 싶다.
else
{
dir = Vector3.down;
}
}
. . . (생략) . . .
}
- 지역변수 dir 을 전역 변수로 변경
- 유니티에서 실행하여 결과 확인
🖥️ Enemy.cs 방향 정해서 그 방향으로 이동
public class Enemy : MonoBehaviour
{
. . . (생략) . . .
// 방향을 전역변수로 만들어서 Start와 Update에서 사용
Vector3 dir;
void Start()
{
// Vector3 dir; -> 삭제
. . . (생략) . . .
}
void Update()
{
// 1. 방향을 구한다.
// Vector3 dir = Vector3.down; -> 삭제
// 2. 이동하고 싶다. 공식 P = P0 + vt
transform.position += dir * speed * Time.deltaTime;
}
. . . (생략) . . .
}
'Project > Unity 게임 제작' 카테고리의 다른 글
[8] 슈팅 게임 제작 (4) (0) | 2023.07.07 |
---|---|
[7] 슈팅 게임 제작 (3) (0) | 2023.07.06 |
[5] 슈팅 게임 제작 (1) (6) | 2023.07.04 |
[4] C# 스크립트 (3) (6) | 2023.06.30 |
[3] C# 스크립트 (2) (6) | 2023.06.29 |