728x90
▶ 근거리 및 원거리 무기 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.TextCore.Text;
using UnityEngine.XR;
public class Weapon : MonoBehaviour
{
//무기id, 프리팹id, damage, 갯수, 속도
public int id;
public int prefabId;
public float damage;
public int count;
public float size;
public float speed;
private ParticleScaler particle;
private float timer;
private void Awake()
{
//부모 오브젝트에 있는 컴포넌트 가져오기
//this.player = GameManager.instance.player;
//this.transform.localPosition = GameManager.instance.player.transform.position;
}
void Update()
{
if (!GameManager.instance.isLive)
{
return;
}
//id 별로 관리
switch (id)
{
case 0:
this.transform.localPosition = Camera.main.WorldToScreenPoint(GameManager.instance.player.transform.position);
//bullet(얼음 오브) 회전시키기
this.transform.Rotate(Vector3.back * this.speed * Time.deltaTime);
break;
case 1:
this.transform.localPosition = Camera.main.WorldToScreenPoint(GameManager.instance.player.transform.position);
break;
case 2:
this.transform.localPosition = Camera.main.WorldToScreenPoint(GameManager.instance.player.stickPoint.transform.position);
this.timer += Time.deltaTime;
if (this.timer > this.speed)
{
//timer 초기화
this.timer = 0f;
//총알 발사
this.Fire();
}
break;
}
}
//id별로 초기화
public void Init(ItemData data)
{
//...Basic Set
this.name = "Weapon" + data.itemId;
//부모 transform 설정
//this.transform.parent = player.transform;
//..Property Set
this.id = data.itemId;
this.damage = data.baseDamage;
this.count = data.baseCount;
this.size = data.baseSize;
for (int i = 0; i < GameManager.instance.pool.prefabs.Length; i++)
{
//무기 프리팹과 오브젝트 풀의 프리팹 연동
if (data.projectile == GameManager.instance.pool.prefabs[i])
{
this.prefabId = i;
Debug.LogFormat("<color=red>prefabId : {0}</color>", this.prefabId);
break;
}
}
switch (id)
{
case 0:
this.speed = 180;
this.Batch();
break;
case 2:
//총알 발사 속도
speed = 0.3f;
break;
}
//player가 가지고 있는 모든 장비에 ApplyGear 적용
//...특정 함수 호출을 모든 자식에게 방송하는 함수
//2번째 인자값으로 'DontRequireReceiver' 추가 (꼭 receiver가 필요하지 않다)
//this.player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
}
//...레벨업 메서드
//레벨업 시 damage와 count 조절하기
public void LevelUp(float damage, int count, float speed, float size)
{
this.damage = damage;
this.count += count;
this.speed = speed;
this.size = size;
//레벨 = 0 , 근접무기일 경우
if (id == 0)
{
//배치해아함
this.Batch();
}
else if(id == 1)
{
//아우라 사이즈 업
this.particle.SizeUp(size);
}
else if(id == 2)
{
this.RateUp();
}
//...BroadcastMessage 초기화
//this.player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
}
//...근거리 bullet(삽) 배치하기
void Batch()
{
for (int i = 0; i < this.count; i++)
{
//...bullet 게임오브젝트 생성 후
//Weapon의 자식으로 넣기 위해 transform가져와 지역변수에 넣기
Transform bullet;
//...i가 childCount 범위 내라면
if (i < this.transform.childCount)
{
//현재 child를 사용
bullet = this.transform.GetChild(i);
}
else
{
//...i가 범위를 넘어서면
//'모자란 수 만큼' 풀링으로 가져옴
bullet = GameManager.instance.pool.Get(prefabId).transform;
//현재 transform을 부모로 설정
//bullet.parent = this.transform;
}
//...bullet위치 player의 위치로 초기화
//levelup 했을때 위치 오류 방지
bullet.localPosition = GameManager.instance.player.transform.position;
bullet.localRotation = Quaternion.identity;
//...회전 각도(z축) 설정
//count(갯수)만큼 회전각 나누어서 배치
Vector3 rot = Vector3.forward * 360 * i / count;
bullet.Rotate(rot);
//Player로 부터 1.5f 거리만큼 떨어져서 위치
bullet.Translate(bullet.right * 2f, Space.World);
//bullet 초기화
bullet.GetComponent<Bullet>().Init(this.damage, -1, Vector3.zero); // -1 == 무한, 무한 관통
}
}
//...원거리 Bullet(총알) 발사
void Fire()
{
if (!GameManager.instance.player.scanner.nearestTarget)
{
return;
}
//가장 가까운 몬스터 위치
Vector3 targetPos = GameManager.instance.player.scanner.nearestTarget.position;
//...총알 방향 설정
Vector3 dir = targetPos - transform.position;
//현재 Vector의 방향은 유지, 크기는 1로 변환
dir = dir.normalized;
Transform bullet = GameManager.instance.pool.Get(prefabId).transform;
bullet.position = this.transform.position;
bullet.rotation = Quaternion.FromToRotation(Vector3.up, dir);
//bullet 초기화
bullet.GetComponent<Bullet>().Init(this.damage, count, dir); // -1 == 무한, 무한 관통
}
void RateUp()
{
switch (id)
{
//id =2 -> 얼음 발사
case 2:
float speed = 180;
this.speed = speed + (speed * this.speed);
break;
}
}
}
using System.Collections;
using System.Collections.Generic;
using System.Net.Http.Headers;
using UnityEngine;
using UnityEngine.UI;
public class Item : MonoBehaviour
{
public ItemData data;
public int level;
public Weapon weapon;
public Gear gear;
private Text txtName;
private Text txtDesc;
private Text txtLevel;
private Image icon;
private Image bg;
void Awake()
{
//GetComponentsInchildren에서 2번째 값으로 가져오기(1번째 : 자기자신)
this.bg = this.GetComponentsInChildren<Image>()[1];
this.icon = this.GetComponentsInChildren<Image>()[2];
//아이콘 넣어주기
this.icon.sprite = data.itemIcon;
this.bg.sprite = data.bgIcon;
Text[] texts = GetComponentsInChildren<Text>();
this.txtLevel = texts[0];
this.txtName = texts[1];
this.txtDesc = texts[2];
//이름 넣어주기
this.txtName.text = data.itemName;
}
//활성화시 동작
void OnEnable()
{
//레벨 1부터 시작
txtLevel.text = string.Format("Lv.{0}", (level + 1).ToString());
switch (data.itemType)
{
case ItemData.eItemType.Orb:
txtDesc.text = string.Format(data.descs[level], data.damages[level] * 100, data.counts[level],data.speeds[level] * 100);
break;
case ItemData.eItemType.Aura:
txtDesc.text = string.Format(data.descs[level], data.damages[level] * 100, data.sizes[level] * 100);
break;
case ItemData.eItemType.Ice_Bolt:
//..count 뺀 나머지 --> 백분율
txtDesc.text = string.Format(data.descs[level], data.damages[level] * 100, data.counts[level]);
break;
case ItemData.eItemType.Heal:
case ItemData.eItemType.Shoe:
case ItemData.eItemType.Shield:
//모두 --> 백분율
txtDesc.text = string.Format(data.descs[level],data.damages[level]*100);
break;
}
}
public void OnClick()
{
switch (data.itemType)
{
case ItemData.eItemType.Orb:
if (level == 0)
{
GameObject newWeapon = new GameObject();
this.weapon = newWeapon.AddComponent<Weapon>();
//Weapon 초기화
this.weapon.Init(data);
this.weapon.transform.Rotate(new Vector3(90, 0, 0));
}
else
{
//...처음 이후의 레벨업은 데미지와 횟수를 계산
//새로운 무기이면 damage 올려줘야함
float nextDamage = data.baseDamage;
int nextCount = 0;
float nextSpeed = data.baseSpeed;
//damages가 백분률 값이므로 곱해준 다음 더해줌
nextDamage += data.baseDamage * data.damages[level];
nextCount += data.counts[level];
nextSpeed += data.baseSpeed * data.speeds[level];
//Weapon 레벨업
weapon.LevelUp(nextDamage, nextCount,nextSpeed,0);
}
//level 증가
level++;
break;
case ItemData.eItemType.Ice_Bolt:
if (level == 0)
{
GameObject newWeapon = new GameObject();
this.weapon = newWeapon.AddComponent<Weapon>();
//Weapon 초기화
this.weapon.Init(data);
}
else
{
//...처음 이후의 레벨업은 데미지와 횟수를 계산
//새로운 무기이면 damage 올려줘야함
float nextDamage = data.baseDamage;
int nextCount = 0;
//damages가 백분률 값이므로 곱해준 다음 더해줌
nextDamage += data.baseDamage * data.damages[level];
nextCount += data.counts[level];
//Weapon 레벨업
weapon.LevelUp(nextDamage, nextCount,0,0);
}
//level 증가
level++;
break;
case ItemData.eItemType.Aura:
if (level == 0)
{
GameObject newWeapon = new GameObject();
this.weapon = newWeapon.AddComponent<Weapon>();
//Weapon 초기화
this.weapon.Init(data);
}
else
{
//...처음 이후의 레벨업은 데미지와 횟수를 계산
//새로운 무기이면 damage 올려줘야함
float nextDamage = data.baseDamage;
float nextSize = data.baseSize;
//damages가 백분률 값이므로 곱해준 다음 더해줌
nextDamage += data.baseDamage * data.damages[level];
nextSize += data.baseSize * data.sizes[level];
//Weapon 레벨업
weapon.LevelUp(nextDamage, 0, 0, nextSize);
}
//level 증가
level++;
break;
case ItemData.eItemType.Shoe:
case ItemData.eItemType.Shield:
case ItemData.eItemType.Heal:
if (level == 0)
{
GameObject newGear = new GameObject();
this.gear = newGear.AddComponent<Gear>();
//Gear 초기화
this.gear.Init(data);
}
else
{
float nextRate = data.damages[level];
gear.LevelUp(nextRate);
}
break;
}
//...레벨 개수 넘기지 않게 로직 추가
//Damages의 배열길이:5 를 넘어가면 Button의 interactable 비활성화(투명하게)
if (level == data.descs.Length)
{
GetComponent<Button>().interactable = false;
}
}
}
부모 - 자식 관계 수정
https://m.blog.naver.com/yoohee2018/221187229189
오브젝트간 움직임을 연결하는 4가지 방법.
Unity 2017.3 ver. 예를 들어 player가 박스를 들고 움직이는 동작을 처리해야 할 때, 여러가지 방법이 있...
blog.naver.com
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.TextCore.Text;
using UnityEngine.XR;
public class Weapon : MonoBehaviour
{
//무기id, 프리팹id, damage, 갯수, 속도
public int id;
public int prefabId;
public float damage;
public int count;
public float size;
public float speed;
private ParticleScaler particle;
private Player player;
private float timer;
private void Awake()
{
//부모 오브젝트에 있는 컴포넌트 가져오기
this.player = GameManager.instance.player;
}
void Update()
{
if (!GameManager.instance.isLive)
{
return;
}
//id 별로 관리
switch (id)
{
case 0:
//bullet(얼음 오브) 회전시키기
this.transform.Rotate(Vector3.back * this.speed * Time.deltaTime);
break;
case 1:
break;
case 2:
if (this.timer > this.speed)
{
//timer 초기화
this.timer = 0f;
//총알 발사
this.Fire();
}
break;
}
}
//id별로 초기화
public void Init(ItemData data)
{
//...Basic Set
this.name = "Weapon" + data.itemId;
//부모 transform 설정
this.transform.parent = this.player.transform;
this.transform.localPosition = Vector3.zero;
//..Property Set
this.id = data.itemId;
this.damage = data.baseDamage;
this.count = data.baseCount;
this.size = data.baseSize;
for (int i = 0; i < GameManager.instance.pool.prefabs.Length; i++)
{
//무기 프리팹과 오브젝트 풀의 프리팹 연동
if (data.projectile == GameManager.instance.pool.prefabs[i])
{
this.prefabId = i;
Debug.LogFormat("<color=red>prefabId : {0}</color>", this.prefabId);
break;
}
}
switch (id)
{
case 0:
this.speed = 180;
this.Batch();
break;
case 2:
//총알 발사 속도
speed = 0.3f;
break;
}
//player가 가지고 있는 모든 장비에 ApplyGear 적용
//...특정 함수 호출을 모든 자식에게 방송하는 함수
//2번째 인자값으로 'DontRequireReceiver' 추가 (꼭 receiver가 필요하지 않다)
//this.player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
}
//...레벨업 메서드
//레벨업 시 damage와 count 조절하기
public void LevelUp(float damage, int count, float speed, float size)
{
this.damage = damage;
this.count += count;
this.speed = speed;
this.size = size;
//레벨 = 0 , 근접무기일 경우
if (id == 0)
{
//배치해아함
this.Batch();
}
else if(id == 1)
{
//아우라 사이즈 업
this.particle.SizeUp(size);
}
else if(id == 2)
{
this.RateUp();
}
//...BroadcastMessage 초기화
//this.player.BroadcastMessage("ApplyGear", SendMessageOptions.DontRequireReceiver);
}
//...근거리 bullet(삽) 배치하기
void Batch()
{
for (int i = 0; i < this.count; i++)
{
//...bullet 게임오브젝트 생성 후
//Weapon의 자식으로 넣기 위해 transform가져와 지역변수에 넣기
Transform bullet;
//...i가 childCount 범위 내라면
if (i < this.transform.childCount)
{
//현재 child를 사용
bullet = this.transform.GetChild(i);
}
else
{
//...i가 범위를 넘어서면
//'모자란 수 만큼' 풀링으로 가져옴
bullet = GameManager.instance.pool.Get(prefabId).transform;
//현재 transform을 부모로 설정
bullet.parent = this.transform;
}
//...bullet위치 player의 위치로 초기화
//levelup 했을때 위치 오류 방지
bullet.localPosition = Vector3.zero;
bullet.localRotation = Quaternion.identity;
//...회전 각도(z축) 설정
//count(갯수)만큼 회전각 나누어서 배치
Vector3 rot = Vector3.forward * 360 * i / count;
bullet.Rotate(rot);
//Player로 부터 1.5f 거리만큼 떨어져서 위치
bullet.Translate(bullet.up * 2f, Space.World);
//bullet 초기화
bullet.GetComponent<Bullet>().Init(this.damage, -1, Vector3.zero); // -1 == 무한, 무한 관통
}
}
//...원거리 Bullet(총알) 발사
void Fire()
{
if (!this.player.scanner.nearestTarget)
{
return;
}
//가장 가까운 몬스터 위치
Vector3 targetPos = this.player.scanner.nearestTarget.position;
//...총알 방향 설정
Vector3 dir = targetPos - transform.position;
//현재 Vector의 방향은 유지, 크기는 1로 변환
dir = dir.normalized;
Transform bullet = GameManager.instance.pool.Get(prefabId).transform;
bullet.position = this.transform.position;
bullet.rotation = Quaternion.FromToRotation(Vector3.up, dir);
//bullet 초기화
bullet.GetComponent<Bullet>().Init(this.damage, count, dir); // -1 == 무한, 무한 관통
}
void RateUp()
{
switch (id)
{
//id =2 -> 얼음 발사
case 2:
float speed = 180;
this.speed = speed + (speed * this.speed);
break;
}
}
}
**문제 해결
Player와 동등한 관계인 빈 오브젝트를 만들고 Player position과 동등하게 해주는 스크립트를 생성하여 넣어준다.
별거 아니지만 그래도 해결해서 다행이다ㅜㅜ
PlayerPos 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerPos : MonoBehaviour
{
void Update()
{
this.transform.position = new Vector3(GameManager.instance.player.transform.position.x, 0, GameManager.instance.player.transform.position.z);
}
}
🎥게임 플레이 영상 및 소감
: 요새 개인적인 일이 좀 생겨서 솔직히 이 프로젝트에 온전히 집중하지 못했다..
그래서 제작 과정을 꼼꼼히 적지 못하여 많이 아쉽고 반성도 많이 했다. 그래도 마무리는 지어서 다행이라고 생각한다.
'3D 콘텐츠 제작 > [위저드 히어로] 제작 일지' 카테고리의 다른 글
[위저드 히어로 04] HUD 만들기 & 레벨업 시스템 (0) | 2023.10.05 |
---|---|
[위저드 히어로 03] 오브젝트 풀링으로 몬스터 생성 & 몬스터 레벨 적용 (0) | 2023.09.27 |
[위저드 히어로 02] 무한맵 생성 (0) | 2023.09.25 |
[위저드 히어로 01] 플레이어 이동 및 카메라 조정 (0) | 2023.09.24 |
[위저드 히어로] 제작 일정 (0) | 2023.09.22 |