아카이브
[개발일지] Undead Survivor 5일차 본문
자동 원거리 공격 구현
Enemy 레이어 추가 후 프리팹에 지정
몬스터 스캔을 담당할 스크립트 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Scanner : MonoBehaviour
{
//범위, 레이어, 스캔 결과 배열, 가장 가까운 목표를 담을 변수 생성
public float scanRange;
public LayerMask targetLayer;
public RaycastHit2D[] targets;
public Transform nearestTarget;
void FixedUpdate() //스캔을 하기위한 로직
{
//CircleCastAll: 원형의 캐스트를 쏘고 모든 결과를 반환하는 함수
//1. 캐스팅 시작 위치 2. 원의 반지름 3. 캐스팅 방향 4. 캐스팅 길이 5.대상 레이어
targets = Physics2D.CircleCastAll(transform.position, scanRange, Vector2.zero, 0, targetLayer);
nearestTarget = GetNearest();
}
//가장 가까운 것을 찾는 함수 추가
Transform GetNearest()
{
Transform result = null;
float diff = 100;
foreach(RaycastHit2D target in targets) {
Vector3 myPos = transform.position;
Vector3 targetPos = target.transform.position;
float curDiff = Vector3.Distance(myPos, targetPos);
if (curDiff < diff)
{
diff = curDiff;
result = target.transform;
}
}
return result;
}
}
플레이어 오브젝트에 Scanner 스크립트 추가 후 설정
총알 생성하기
Bullet 1프리팹, Weapon 1오브젝트 설정
풀 매니저에 Bullet 1프리팹 추가
Weapon.cs와 Player.cs에 코드 추가
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 = GetComponentInParent<Player>(); //부모의 컴포넌트 가져오기
}
void Start()
{
Init();
}
// Update is called once per frame
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
if (Input.GetButtonDown("Jump"))
{
LevelUp(20, 5);
}
}
public void LevelUp(float damage, int count)
{
this.damage = damage;
this.count += count;
if(id ==0)
Batch();
}
public void Init()
{
switch (id)
{
case 0:
speed = 150;
Batch();
break;
default:
speed = 0.3f;
break;
}
}
void Batch()
{
for(int index = 0; index < count; index++)
{
Transform bullet;
if(index < transform.childCount)
{
bullet = transform.GetChild(index); //인덱스가 childCount 범위 내라면 GetChild 함수로 가져오기
}
else
{
//기존 오브젝트 먼저 활용하고 모자란 것은 풀링에서 가져오기
bullet = GameManager.instance.pool.Get(prefabId).transform; //가져온 오브젝트의 Transform을 지역변수로 저장
bullet.parent = transform;
}
bullet.localPosition = Vector3.zero;
bullet.localRotation = Quaternion.identity;
Vector3 rotVec = Vector3.forward * 360 * index / count;
bullet.Rotate(rotVec);
bullet.Translate(bullet.up * 1.5f, Space.World);
bullet.GetComponent<Bullet>().Init(damage, -1); //-1 은 무한으로 관통하는 근접공격
}
}
void Fire()
{
if (!player.scanner.nearestTarget)
return;
Transform bullet = GameManager.instance.pool.Get(prefabId).transform;
bullet.position = transform.position;
}
}
총알 발사
Bullet 1 프리팹에 Rigidbody 부착
Bullet 스크립트에 코드 작성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float damage;
public int per;
Rigidbody2D rigid;
void Awake()
{
rigid = GetComponent<Rigidbody2D>();
}
public void Init(float damage, int per, Vector3 dir)
{
this.damage = damage;
this.per = per;
if(per > -1) {
rigid.velocity = dir * 15f; //속력을 곱해서 총알이 날아가는 속도 증가
}
}
void OnTriggerEnter2D(Collider2D collision)
{
if (!collision.CompareTag("Enemy") || per ==-1)
return;
per--;
if(per == -1) {
rigid.velocity = Vector2.zero;
gameObject.SetActive(false);
}
}
}
Weapon.cs에 코드 추가
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 = GetComponentInParent<Player>(); //부모의 컴포넌트 가져오기
}
void Start()
{
Init();
}
// Update is called once per frame
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
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()
{
switch (id)
{
case 0:
speed = 150;
Batch();
break;
default:
speed = 0.3f;
break;
}
}
void Batch()
{
for(int index = 0; index < count; index++)
{
Transform bullet;
if(index < transform.childCount)
{
bullet = transform.GetChild(index); //인덱스가 childCount 범위 내라면 GetChild 함수로 가져오기
}
else
{
//기존 오브젝트 먼저 활용하고 모자란 것은 풀링에서 가져오기
bullet = GameManager.instance.pool.Get(prefabId).transform; //가져온 오브젝트의 Transform을 지역변수로 저장
bullet.parent = transform;
}
bullet.localPosition = Vector3.zero;
bullet.localRotation = Quaternion.identity;
Vector3 rotVec = Vector3.forward * 360 * index / count;
bullet.Rotate(rotVec);
bullet.Translate(bullet.up * 1.5f, Space.World);
bullet.GetComponent<Bullet>().Init(damage, -1, Vector3.zero); //-1 은 무한으로 관통하는 근접공격
}
}
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 스크립트에 전달
bullet.GetComponent<Bullet>().Init(damage, count, dir);
}
}
'2D 콘텐츠 제작' 카테고리의 다른 글
2D 프로젝트 개발 발표 (0) | 2023.09.21 |
---|---|
[개발일지] Undead Survivor 4일차 (0) | 2023.09.19 |
[개발일지] Undead Survivor 3일차 (0) | 2023.09.15 |
[개발일지] Undead Survivor 2일차 (0) | 2023.09.14 |
[개발일지] Undead Survivor 1일차 (0) | 2023.09.13 |