일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 4월
- 입문
- 유니티
- 개인 프로젝트
- 2월
- 2024년
- 7월
- 5월
- 코딩 테스트
- 다이나믹 프로그래밍
- c++
- 1월
- C/C++
- 백준
- 자료 구조
- 단계별로 풀어보기
- 골드메탈
- 개인 프로젝트 - 런앤건
- todolist
- 3월
- 프로그래머스
- 2022년
- 10월
- 수학
- 2023년
- 2025년
- 코딩 기초 트레이닝
- 게임 엔진 공부
- 기초
- 유니티 심화과정
- Today
- Total
기록 보관소
[Unity/유니티] 기초-뱀서라이크: 능력 업그레이드 구현[11] 본문
개요
유니티 독학을 위해 아래 링크의 골드메탈님의 영상들을 보고 직접 따라 해보면서 진행 상황을 쓰고 배웠던 점을 요약한다.
https://youtube.com/playlist?list=PLO-mt5Iu5TeYI4dbYwWP8JqZMC9iuUIW2
📚유니티 기초 강좌
유니티 게임 개발을 배우고 싶은 분들을 위한 기초 강좌
www.youtube.com
뱀서라이크: 능력 업그레이드 구현[11]
1. 아이템 데이터 만들기
//ItemData Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Item", menuName = "Scriptble Object/ItemData")]
public class ItemData : ScriptableObject {
public enum ItemType { Melee, Range, Glove, Shoe, Heal }
[Header("# Main Info")]
public ItemType itemType;
public int itemId;
public string itemName;
public string itemDesc;
public Sprite itemIcon;
[Header("# Level Info")]
public float baseDamage;
public int baseCount;
public float[] damages;
public int[] counts;
[Header("# Weapon")]
public GameObject projectile;
}
- CreateAssetMenu() : 커스텀 메뉴를 생성하는 속성
2. 레벨업 버튼 제작
//Item Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Item : MonoBehaviour {
public ItemData data;
public int level;
public Weapon weapon;
Image icon;
Text textLevel;
void Awake() {
icon = GetComponentsInChildren<Image>()[1];
icon.sprite = data.itemIcon;
Text[] texts = GetComponentsInChildren<Text>();
textLevel = texts[0];
}
void LateUpdate() {
textLevel.text = "Lv." + (level + 1);
}
}
- 버튼 클릭 이벤트와 연결할 함수 추가
//Item Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Item : MonoBehaviour {
public ItemData data;
public int level;
public Weapon weapon;
Image icon;
Text textLevel;
void Awake() {
icon = GetComponentsInChildren<Image>()[1];
icon.sprite = data.itemIcon;
Text[] texts = GetComponentsInChildren<Text>();
textLevel = texts[0];
}
void LateUpdate() {
textLevel.text = "Lv." + (level + 1);
}
public void OnClick() {
switch(data.itemType) {
case ItemData.ItemType.Melee:
case ItemData.ItemType.Range:
break;
case ItemData.ItemType.Glove:
break;
case ItemData.ItemType.Shoe:
break;
case ItemData.ItemType.Heal:
break;
}
level++;
if (level == data.damages.Length) {
//작성한 레벨 데이터 개수를 넘지 않도록 만들기
GetComponent<Button>().interactable = false;
}
}
}
3. 무기 업그레이드
//Item Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Item : MonoBehaviour {
public ItemData data;
public int level;
public Weapon weapon;
Image icon;
Text textLevel;
void Awake() {
icon = GetComponentsInChildren<Image>()[1];
icon.sprite = data.itemIcon;
Text[] texts = GetComponentsInChildren<Text>();
textLevel = texts[0];
}
void LateUpdate() {
textLevel.text = "Lv." + (level + 1);
}
public void OnClick() {
switch(data.itemType) {
case ItemData.ItemType.Melee:
case ItemData.ItemType.Range:
if (level == 0) {
GameObject newWeapon = new GameObject();
weapon = newWeapon.AddComponent<Weapon>();
weapon.Init(data);
}
else {
float nextDamage = data.baseDamage;
int nextCount = 0;
nextDamage += data.baseDamage * data.damages[level];
nextCount += data.counts[level];
weapon.LevelUp(nextDamage, nextCount);
}
break;
case ItemData.ItemType.Glove:
break;
case ItemData.ItemType.Shoe:
break;
case ItemData.ItemType.Heal:
break;
}
level++;
if (level == data.damages.Length) {
//작성한 레벨 데이터 개수를 넘지 않도록 만들기
GetComponent<Button>().interactable = false;
}
}
}
//Weapon Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Weapon : MonoBehaviour {
public int id;
public int prefabId;
public float damage;
public int count;
public float speed;
float timer;
Player player;
void Awake() {
player = GameManager.instance.player;
}
void Update() {
switch (id) {
case 0:
transform.Rotate(Vector3.back * speed * Time.deltaTime);
break;
default:
timer += Time.deltaTime;
if (timer > speed) {
timer = 0f;
Fire();
}
break;
}
// .. Test Code ..
if (Input.GetButtonDown("Jump")) {
LevelUp(10, 1);
}
}
public void LevelUp(float damage, int count) {
this.damage = damage;
this.count += count;
if (id == 0)
Batch();
}
public void Init(ItemData data) {
// Basic Set
name = "Weapon " + data.itemId;
transform.parent = player.transform;
transform.localPosition = Vector3.zero;
// Property Set
id = data.itemId;
damage = data.baseDamage;
count = data.baseCount;
for (int index = 0; index < GameManager.instance.pool.prefabs.Length; index++) {
if (data.projectile == GameManager.instance.pool.prefabs[index]) { //프리펩이 같은건지 확인
prefabId = index;
break;
}
}
switch (id) {
case 0:
speed = 150;
Batch();
break;
default:
speed = 0.4f;
break;
}
}
void Batch() { //생성된 무기를 배치하는 함수
for (int index = 0; index < count; index++) {
Transform bullet;
if (index < transform.childCount) {
bullet = transform.GetChild(index); //기존 오브젝트가 있으면 먼저 활용
}
else {
bullet = GameManager.instance.pool.Get(prefabId).transform; //모자라면 풀링에서 가져옴
bullet.parent = transform;
}
bullet.localPosition = Vector3.zero; //무기 위치 초기화
bullet.localRotation = Quaternion.identity; //무기 회전값 초기화
Vector3 rotVec = Vector3.forward * 360 * index / count; //개수에 따라 360도 나누기
bullet.Rotate(rotVec);
bullet.Translate(bullet.up * 1.5f, Space.World); //무기 위쪽으로 이동
bullet.GetComponent<Bullet>().Init(damage, -1, Vector3.zero); //-1 is Infinity Per. 무한 관통.
}
}
void Fire() {
if (!player.scanner.nearestTarget)
return;
Vector3 targetPos = player.scanner.nearestTarget.position;
Vector3 dir = targetPos - transform.position;
dir = dir.normalized;
Transform bullet = GameManager.instance.pool.Get(prefabId).transform;
bullet.position = transform.position;
bullet.rotation = Quaternion.FromToRotation(Vector3.up, dir); //FromToRotation(지정된 축을 중심으로 목표를 향해 회전하는 함수
bullet.GetComponent<Bullet>().Init(damage, count, dir);
}
}
4. 장비 업그레이드
//Gear Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gear : MonoBehaviour {
public ItemData.ItemType type;
public float rate;
public void Init(ItemData data) {
// Basic Set
name = "Gear " + data.itemId;
transform.parent = GameManager.instance.player.transform;
transform.localPosition = Vector3.zero;
// Property Set
type = data.itemType;
rate = data.damages[0];
ApplyGear();
}
public void LevelUp(float rate) {
this.rate = rate;
ApplyGear();
}
void ApplyGear () { //장비가 새롭게 추가되거나 레벨업 할때 호출
switch (type) {
case ItemData.ItemType.Glove:
RateUp();
break;
case ItemData.ItemType.Shoe:
SpeedUp();
break;
}
}
void RateUp() {
Weapon[] weapons = transform.parent.GetComponentsInChildren<Weapon>();
foreach (Weapon weapon in weapons) {
switch (weapon.id) {
case 0:
weapon.speed = 150 + (150 * rate);
break;
default:
weapon.speed = 0.5f * (1f - rate);
break;
}
}
}
void SpeedUp() {
float speed = 3;
GameManager.instance.player.speed = speed + speed * rate;
}
}
//Item Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Item : MonoBehaviour {
public ItemData data;
public int level;
public Weapon weapon;
public Gear gear;
Image icon;
Text textLevel;
void Awake() {
icon = GetComponentsInChildren<Image>()[1];
icon.sprite = data.itemIcon;
Text[] texts = GetComponentsInChildren<Text>();
textLevel = texts[0];
}
void LateUpdate() {
textLevel.text = "Lv." + (level + 1);
}
public void OnClick() {
switch(data.itemType) {
case ItemData.ItemType.Melee:
case ItemData.ItemType.Range:
if (level == 0) {
GameObject newWeapon = new GameObject();
weapon = newWeapon.AddComponent<Weapon>();
weapon.Init(data);
}
else {
float nextDamage = data.baseDamage;
int nextCount = 0;
nextDamage += data.baseDamage * data.damages[level];
nextCount += data.counts[level];
weapon.LevelUp(nextDamage, nextCount);
}
level++;
break;
case ItemData.ItemType.Glove:
case ItemData.ItemType.Shoe:
if (level == 0) {
GameObject newGear = new GameObject();
gear = newGear.AddComponent<Gear>();
gear.Init(data);
}
else {
float nextRate = data.damages[level];
gear.LevelUp(nextRate);
}
level++;
break;
case ItemData.ItemType.Heal:
GameManager.instance.health = GameManager.instance.maxHealth;
break;
}
if (level == data.damages.Length) {
//작성한 레벨 데이터 개수를 넘지 않도록 만들기
GetComponent<Button>().interactable = false;
}
}
}
//Weapon Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Weapon : MonoBehaviour {
public int id;
public int prefabId;
public float damage;
public int count;
public float speed;
float timer;
Player player;
void Awake() {
player = GameManager.instance.player;
}
void Update() {
switch (id) {
case 0:
transform.Rotate(Vector3.back * speed * Time.deltaTime);
break;
default:
timer += Time.deltaTime;
if (timer > speed) {
timer = 0f;
Fire();
}
break;
}
// .. Test Code ..
if (Input.GetButtonDown("Jump")) {
LevelUp(10, 1);
}
}
public void LevelUp(float damage, int count) {
this.damage = damage;
this.count += count;
if (id == 0)
Batch();
player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
}
public void Init(ItemData data) {
// Basic Set
name = "Weapon " + data.itemId;
transform.parent = player.transform;
transform.localPosition = Vector3.zero;
// Property Set
id = data.itemId;
damage = data.baseDamage;
count = data.baseCount;
for (int index = 0; index < GameManager.instance.pool.prefabs.Length; index++) {
if (data.projectile == GameManager.instance.pool.prefabs[index]) { //프리펩이 같은건지 확인
prefabId = index;
break;
}
}
switch (id) {
case 0:
speed = 150;
Batch();
break;
default:
speed = 0.4f;
break;
}
//플레이어가 가지고 있는 모든 Gear에 대해 ApplyGear를 실행하게 함. 나중에 추가된 무기에도 영향을 주기 위함.
player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
}
void Batch() { //생성된 무기를 배치하는 함수
for (int index = 0; index < count; index++) {
Transform bullet;
if (index < transform.childCount) {
bullet = transform.GetChild(index); //기존 오브젝트가 있으면 먼저 활용
}
else {
bullet = GameManager.instance.pool.Get(prefabId).transform; //모자라면 풀링에서 가져옴
bullet.parent = transform;
}
bullet.localPosition = Vector3.zero; //무기 위치 초기화
bullet.localRotation = Quaternion.identity; //무기 회전값 초기화
Vector3 rotVec = Vector3.forward * 360 * index / count; //개수에 따라 360도 나누기
bullet.Rotate(rotVec);
bullet.Translate(bullet.up * 1.5f, Space.World); //무기 위쪽으로 이동
bullet.GetComponent<Bullet>().Init(damage, -1, Vector3.zero); //-1 is Infinity Per. 무한 관통.
}
}
void Fire() {
if (!player.scanner.nearestTarget)
return;
Vector3 targetPos = player.scanner.nearestTarget.position;
Vector3 dir = targetPos - transform.position;
dir = dir.normalized;
Transform bullet = GameManager.instance.pool.Get(prefabId).transform;
bullet.position = transform.position;
bullet.rotation = Quaternion.FromToRotation(Vector3.up, dir); //FromToRotation(지정된 축을 중심으로 목표를 향해 회전하는 함수
bullet.GetComponent<Bullet>().Init(damage, count, dir);
}
}
- BroadcastMessage : 특정 함수 호출을 모든 자식에게 방송하는 함수
'유니티 프로젝트 > 뱀서라이크' 카테고리의 다른 글
[Unity/유니티] 기초-뱀서라이크: 레벨업 시스템[12] (0) | 2023.07.14 |
---|---|
[Unity/유니티] 기초-뱀서라이크: 플레이어 무기 장착 표현하기[11+] (0) | 2023.07.13 |
[Unity/유니티] 기초-뱀서라이크: HUD 제작하기[10] (0) | 2023.07.11 |
[Unity/유니티] 기초-뱀서라이크: 타격감 있는 몬스터 처치 만들기[09] (0) | 2023.07.10 |
[Unity/유니티] 기초-뱀서라이크: 자동 원거리 공격 구현[08] (0) | 2023.06.04 |