[ProjectT]/개발일지

[21.11.24] 조이스틱 공격_02

치명적흑형 2021. 11. 24. 18:15

 

 

조이스틱 첫 조작시 전방으로 총알이 나가는 문제가 있어서 수정중

- 조이스틱 조작후 좌표를 계산해서 회전하다보니 회전보다 조작이 먼저 실행되어서 생기는 문제로 보임

- 회전이 되는 시점에 액션을 받아와 공격을 하도록 수정하여 해결

 


오브젝트 풀링을 이용한 총알 재사용

 

우측 불릿 프리팹이 활성화 비활성화되며 재사용 되는 모습


최초에 10개를 생성하고 10개 이상 사용될때 새로 만들어 지는데

사용이 다 되고 공격을 안한다면 10개까지만 저장할수 있도록 해봐야겠다. 


전체코드

 

플레이어

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class TestPlayer : MonoBehaviour
{
    public float speed;
    [SerializeField]
    private Joystick moveJoystick;
    [SerializeField]
    private Joystick attackJoystick;

    //플레이어 방향 0 or 1
    private int reverseScale = 0;

    [SerializeField]
    private GameObject weapon;

    //애니메이션 상태
    [SerializeField]
    private Animator animator;
    private bool isRun;
    private bool isDie;

    //공격 조이스틱 방향 액션
    public UnityAction<float> weaponAngleAction;

    public void FixedUpdate()
    {
        //이동(조이스틱)
        Vector2 moveDir = Vector2.up * this.moveJoystick.Vertical + Vector2.right * this.moveJoystick.Horizontal;

        if (moveDir.x < 0)
        {
            if (this.reverseScale != 0)
            {
                this.reverseScale = 0;
                this.transform.localScale = new Vector2(this.transform.localScale.x * -1, this.transform.localScale.y);
            }
        }
        else if (moveDir.x > 0)
        {
            if (this.reverseScale != 1)
            {
                this.reverseScale = 1;
                this.transform.localScale = new Vector2(this.transform.localScale.x * -1, this.transform.localScale.y);
            }
        }
        this.transform.Translate(moveDir * this.speed * Time.deltaTime);

        //이동(키보드)

        //좌 이동
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            //방향 * 속도 * 시간
            this.transform.Translate(Vector2.left * this.speed * Time.deltaTime);

            if (this.reverseScale != 0)
            {
                this.reverseScale = 0;
                this.transform.localScale = new Vector2(this.transform.localScale.x * -1, this.transform.localScale.y);
            }
        }

        //우 이동
        if (Input.GetKey(KeyCode.RightArrow))
        {
            this.transform.Translate(Vector2.right * this.speed * Time.deltaTime);

            if (this.reverseScale != 1)
            {
                this.reverseScale = 1;
                this.transform.localScale = new Vector2(this.transform.localScale.x * -1, this.transform.localScale.y);
            }
        }

        //상 이동
        if (Input.GetKey(KeyCode.UpArrow))
        {
            this.transform.Translate(Vector2.up * this.speed * Time.deltaTime);
        }

        //하 이동
        if (Input.GetKey(KeyCode.DownArrow))
        {
            this.transform.Translate(Vector2.down * this.speed * Time.deltaTime);
        }

        //애니메이션(키보드)
        if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.DownArrow))
        {
            this.isRun = true;
            this.animator.SetBool("Run", this.isRun);
        }
        else
        {
            this.isRun = false;
            this.animator.SetBool("Run", this.isRun);
        }

        //공격(무기 회전)
        Vector2 attackDir = Vector2.up * this.attackJoystick.Vertical + Vector2.right * this.attackJoystick.Horizontal;
        float weaponAngle = GetAngle(attackDir, Vector2.zero);
        if(this.transform.localScale.x < 0)
        {
            weaponAngle += 180;
        }
        if(this.attackJoystick.Direction == Vector2.zero)
        {
            this.weapon.transform.rotation = Quaternion.Euler(0, 0, 0);
        }
        else
        {
            this.weapon.transform.rotation = Quaternion.Euler(0, 0, weaponAngle);
            this.weaponAngleAction(weaponAngle);
        }

        //애니메이션(조이스틱)
        //if(moveJoystick.Direction == Vector2.zero)
        //{
        //    this.isRun = false;
        //    this.animator.SetBool("Run", this.isRun);
        //}
        //else
        //{
        //    this.isRun = true;
        //    this.animator.SetBool("Run", this.isRun);
        //}
    }
    public static float GetAngle(Vector2 vStart, Vector2 vEnd)
    {
        Vector2 v = vEnd - vStart;

        return Mathf.Atan2(v.y, v.x) * Mathf.Rad2Deg;
    }
}

 

불릿 제너레이터

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestBulletGenerator : MonoBehaviour
{
    [SerializeField]
    private GameObject bulletPrefab;
    [SerializeField]
    private Transform weapon;
    [SerializeField]
    private TestPlayer testPlayer;

    public float delte;
    public float span;

    //오브젝트 풀링
    public GameObject bullet;
    public int bulletPoolCount = 10;
    public Queue<GameObject> bulletPool = new Queue<GameObject>();

    void Start()
    {
        this.testPlayer.weaponAngleAction = (weaponAngle) => {
            this.Attack(weaponAngle);
        };

        for (int i = 0; i < bulletPoolCount; i++)
        {
            CreateBulletPool();
        }
    }

    void Update()
    {
        this.delte = Mathf.Clamp(this.delte += Time.deltaTime, 0, this.span);
    }
    private void Attack(float weaponAngle)
    {
        //Debug.Log(this.attackJoystick.Direction);

        if (this.delte >= this.span)
        {
            this.delte = 0;
            //GameObject go = Instantiate(bulletPrefab);
            GameObject go = this.DequeueBullet();
            go.transform.position = weapon.transform.position;
            if (this.transform.localScale.x < 0)
            {
                go.transform.eulerAngles = new Vector3(0, 0, weaponAngle - 90);
            }
            else
            {
                go.transform.eulerAngles = new Vector3(0, 0, weaponAngle + 90);
            }
        }
    }
    private void CreateBulletPool()
    {
        GameObject temp = Instantiate(bulletPrefab);
        temp.GetComponent<TestBullet>().Init(this);
        temp.SetActive(false);
        bulletPool.Enqueue(temp);
    }
    public GameObject DequeueBullet()
    {
        if (this.bulletPool.Count <= 0)
        {
            CreateBulletPool();
        }

        GameObject dequeueObject = this.bulletPool.Dequeue();
        //dequeueObject.GetComponent<TestBullet>().CleanUp();
        dequeueObject.SetActive(true);
        return dequeueObject;
    }
    public void EnqueueBullet(GameObject enqueueObject)
    {
        enqueueObject.SetActive(false);
        this.bulletPool.Enqueue(enqueueObject);
    }
}

 

불릿

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestBullet : MonoBehaviour
{
    [SerializeField]
    private float bulletSpeed;

    private TestBulletGenerator testBulletGenerator;

    public void Init(TestBulletGenerator testBulletGenerator)
    {
        this.testBulletGenerator = testBulletGenerator;
    }
    void Update()
    {
        this.transform.Translate(Vector2.up * this.bulletSpeed * Time.deltaTime);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.tag == "Wall")
        {
            //Destroy(this.gameObject);
            this.testBulletGenerator.EnqueueBullet(this.gameObject);
        }
        if (collision.tag == "Enemy")
        {
            //Destroy(this.gameObject);
            this.testBulletGenerator.EnqueueBullet(this.gameObject);
        }
    }
    //public void CleanUp()
    //{
    //}
}

델타가 스판을 초과하지 못하도록 사용

Mathf.Clamp
최대/최소값 사이의 float 값이 value 범위 외의 값이 되지 않도록 합니다.
https://docs.unity3d.com/kr/530/ScriptReference/Mathf.Clamp.html

 


오브젝트 풀링 참고 블로그
https://notyu.tistory.com/64