2D 슈팅 게임을 만들어 보고 있는데 여러가지 형태의 총알 발사 형태가 필요해서 구현해 보았습니다.
Player 또는 적 -> 총알 발사하게 되는데 이것을 여기에서는 BulletGroupTest Object 생성하고 BulletGroupTest 는 여러발의 BulletTest(총알)을 생성 하도록 샘플을 만들어 보았습니다.
실제 동작 화면부터 보겠습니다.
가장 핵심의 되는 코드부터 설명하겠습니다.
BulletGroupTest -> BulletTest 를 생성 하는 코드
public void Init() { // < 방사형 if (bulletType == 0) { Vector3 targetPos = target.position; Vector3 dir = targetPos - transform.position; dir = dir.normalized; float baseAngle = 10f; float startAngle = -Mathf.Floor((bulletCount - 1) / 2) * (baseAngle) - baseAngle / 2 * (1 - bulletCount % 2); Vector3 curVec = Rotate_z(dir, startAngle); for (int i = 0; i < bulletCount; i++) { GameObject bullet = Instantiate(bulletPrefabPoolId, transform); bullet.transform.position = transform.position; bullet.transform.rotation = Quaternion.FromToRotation(Vector3.up, curVec); bullet.GetComponent<BulletTest>().Init(bulletDamage, bulletSpeed, bulletPiercing, curVec, bulletLifeTime); startAngle += baseAngle; curVec = Rotate_z(dir, startAngle); } } Destroy(gameObject,3f); } Vector3 Rotate_z(Vector3 dir, float angle) { // angle을 라디안으로 변환합니다. float radian = angle * Mathf.Deg2Rad; Vector3 ret = new Vector3(0, 0, 0); // 삼각함수를 이용하여 ret의 x, y, z 세 원소를 계산합니다. ret.x = dir.x * Mathf.Cos(radian) - dir.y * Mathf.Sin(radian); // x 방향으로 회전합니다. ret.y = dir.x * Mathf.Sin(radian) + dir.y * Mathf.Cos(radian); // y 방향으로 회전합니다. ret.z = dir.z; // z 방향은 변하지 않습니다. // ret를 결과로 반환합니다. return ret; }
이 부분이 하는 핵심 코드 입니다.
Bullet 를 생성하고 탄환을 일정 각도로 회전을 줍니다. 여기에서는 10 도 만큼 회전시키는 코드입니다. Rotate_z 함수는 Vector3 를 z축으로 특정 각도 만큼 회전시키는 함수입니다.
TestPlayer 코드 입니다.
해당 코드는 TestPlayer에 Componet로 추가 되어 있습니다.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestPlayer : MonoBehaviour { public GameObject bulletGroup; public int bulletCount = 3; public Transform target; public float speed = 100f; Rigidbody2D rb; private void Awake() { rb = GetComponent<Rigidbody2D>(); } // Start is called before the first frame update void Start() { } // Update is called once per frame void FixedUpdate() { float moveX; float moveY; moveX = Input.GetAxis("Horizontal"); moveY = Input.GetAxis("Vertical"); Vector3 moveVector = new Vector3(moveX, moveY, 0f); rb.velocity = moveVector.normalized * Time.fixedDeltaTime * speed; if (Input.GetButtonDown("Jump")) { GameObject bGroup = Instantiate(bulletGroup, transform); BulletGroupTest bGT = bGroup.GetComponent<BulletGroupTest>(); bGT.bulletType = 0; bGT.bulletCount = bulletCount; bGT.bulletSpeed = 5; bGT.target = target; bGT.Init(); } } }
방향키로 움직이고 Jump키를 누르면 Bullet Group를 생성 시키는 함수 입니다.
앞서 BulletGroupTest의 핵심 코드를 설명하긴 했지만 전체 코드 입니다.
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class BulletGroupTest : MonoBehaviour { public int bulletType; // 0:총알 형태 public int bulletCount; public float bulletDamage; public float bulletSpeed; public int bulletPiercing; public float bulletLifeTime; public Transform target; public GameObject bulletPrefabPoolId; public float bulletSize; void Awake() { } public void Init() { // < 방사형 if (bulletType == 0) { Vector3 targetPos = target.position; Vector3 dir = targetPos - transform.position; dir = dir.normalized; float baseAngle = 10f; float startAngle = -Mathf.Floor((bulletCount - 1) / 2) * (baseAngle) - baseAngle / 2 * (1 - bulletCount % 2); Vector3 curVec = Rotate_z(dir, startAngle); for (int i = 0; i < bulletCount; i++) { GameObject bullet = Instantiate(bulletPrefabPoolId, transform); bullet.transform.position = transform.position; bullet.transform.rotation = Quaternion.FromToRotation(Vector3.up, curVec); bullet.GetComponent<BulletTest>().Init(bulletDamage, bulletSpeed, bulletPiercing, curVec, bulletLifeTime); startAngle += baseAngle; curVec = Rotate_z(dir, startAngle); } } Destroy(gameObject,3f); } Vector3 Rotate_z(Vector3 dir, float angle) { // angle을 라디안으로 변환합니다. float radian = angle * Mathf.Deg2Rad; Vector3 ret = new Vector3(0, 0, 0); // 삼각함수를 이용하여 ret의 x, y, z 세 원소를 계산합니다. ret.x = dir.x * Mathf.Cos(radian) - dir.y * Mathf.Sin(radian); // x 방향으로 회전합니다. ret.y = dir.x * Mathf.Sin(radian) + dir.y * Mathf.Cos(radian); // y 방향으로 회전합니다. ret.z = dir.z; // z 방향은 변하지 않습니다. // ret를 결과로 반환합니다. return ret; } }
이번에는 날아가는 총알에 대한 코드입니다.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BulletTest : MonoBehaviour { public float damage; public float speed; public int piercing; public float lifeTime; Rigidbody2D rigid; Animator animator; float accTime; void Awake() { rigid = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); } public void Init(float damage, float speed, int piercing, Vector3 dir, float lifeTime, bool autoDie = false) { Debug.Log(speed); Debug.Log(dir); this.damage = damage; this.piercing = piercing; this.speed = speed; this.lifeTime = lifeTime; this.accTime = 0; rigid.velocity = dir * speed; } public void FixedUpdate() { accTime += Time.fixedDeltaTime; if (accTime > lifeTime) { Destroy(gameObject); } } }
BulletTest 는 총알 이미지로 Prefab화 시켰습니다.
댓글 없음:
댓글 쓰기