1인 개발/나홀로 성 지키기

나홀로 성 지키기 개인 프로젝트 7일차

잼잼재미 2024. 3. 25. 01:50

구현 내용


1. 화살 구현


 

  • Rigidbody와 AddForce로 포물선 운동 구현
  • 코루틴으로 좌, 우 반복해서 발사
  • 오브젝트 풀 사용

https://kkln2486.tistory.com/367

 

2D 화살 구현 (포물선 운동)

구현 방법 1. 스크립트 작성 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Arrow : MonoBehaviour { public float _power; private Rigidbody2D _rigidbody; private void Awake() { _rigidbody = GetComponent()

kkln2486.tistory.com

 

 

2. 원거리 적 구현


 

  • 기존 Enemy 상태패턴에서 Enum을 추가해서 활용
  • Physics2D.Raycast로 Castle Layer를 감지해서 AttackState로 전환
  • Bullet 프리팹 추가
  • 오브젝트 풀 적용

 

_layerMask = 1 << LayerMask.NameToLayer("Castle");

if (_attackType == Type.Ranged)
{
    Debug.DrawRay(transform.position - new Vector3(0, 2, 0), Vector2.left * _enemyController.EnemyData.Distance, new Color(1, 0, 0));
    _hitInfo = Physics2D.Raycast(transform.position - new Vector3(0, 2, 0), Vector2.left, _enemyController.EnemySO.Distance, _layerMask);

    if (_hitInfo.collider != null)
    {
        if (_hitInfo.transform.CompareTag("Castle"))
        {
            _enemyController.IsAttack = true;
        }
    }
}

 

Raycast가 Castle 외의 Layer를 감지하지 못하도록 설정하고 Castle을 감지하면 AttackState로 전환되도록 구현

 

 

트러블 슈팅


1. 화살 방향 설정


 

 

private void Start()
{
    _rigidbody.AddForce(new Vector2(1, 1) * _power, ForceMode2D.Impulse);
}

 

위와 같이 AddForce를 이용해서 화살의 포물선 운동을 구현했다. 위 방법은 Vector 값으로 원하는 방향을 계산해서 설정해야지 화살 방향을 조절 할 수 있었다. 그리고 화살이 끝 부분이 고정되어 있어서 화살의 방향을 바꾸는 방법이 필요했다.

 

 

private void Start()
{
    _rigidbody.AddForce(transform.right * _power, ForceMode2D.Impulse);
}

private void Update()
{
    transform.right = _rigidbody.velocity;
}

 

위와 같이 transform.rigth로 오브젝트가 향하고 있는 방향의 오른쪽을 벡터로 받아 올 수 있었다. 그리고 velocity에는 날아가는 방향의 대한 정보도 포함되어 있기 때문에 Update문에서 위와 같이 화살의 끝 부분이 날아가는 방향과 동일하게 설정이 가능했다.

 

 

 

Rotation의 Z 값을 원하는대로 설정하면 그 방향으로 화살이 날아간다.

 

 

 

해결 완료!

 

 

2. 화살의 오브젝트 풀 사용 시, rotation의 변경


 

 

private void Awake()
{
	_rigidbody = GetComponent<Rigidbody2D>();
}

private void Start()
{
    _rigidbody.AddForce(transform.right * _castleSO.Speed, ForceMode2D.Impulse);
_originAngle = transform.rotation.z;
}

private void OnEnable()
{
    if(_rigidbody != null)
    {
        transform.rotation = Quaternion.Euler(0, 0, _originAngle);
        _rigidbody.AddForce(transform.right * _castleSO.Speed, ForceMode2D.Impulse);
    }
}
IEnumerator COCastleArrow()
{
    while (true)
    {
        yield return new WaitForSeconds(CastleSO.AttackCoolTime);

        GameManager.I.ObjectPoolManager.ActivePrefab("ArrowRight", _arrowRight.position);
    }
}

 

초기 Rotation의 Z 값을 저장하고 오브젝트 풀로 재사용 될 때마다, rotation 값을 초기화 했지만, 위 사진과 같이 설정한 Z 값으로 초기화 되지 않았다.

 

private void Start()
{
    _rigidbody = GetComponent<Rigidbody2D>();
    _rigidbody.AddForce(transform.right * _castleSO.Speed, ForceMode2D.Impulse);
    _originAngle = transform.rotation.eulerAngles.z;
    Debug.Log("초기 z : " + _originAngle);
}

private void OnEnable()
{
    if (_rigidbody != null)
    {
        transform.rotation = Quaternion.Euler(0, 0, _originAngle);
        _rigidbody.AddForce(transform.right * _castleSO.Speed, ForceMode2D.Impulse);
    }
}

 

 

두 가지 문제점이 있어서 위와 같이 수정했다.

먼저 이벤트 함수의 실행 순서다. Awake - OnEnable - Start 순으로 실행되기 때문에 _rigidbody != null 조건이 처음부터 실행되지 않고 게임 실행 즉시 OnEnable이 실행되었다. 그래서 _originAngle에는 초기화가 실행되지 않았기 때문에 0 값이 적용 된 것이다. OnEnable은 프리팹이 재사용 될 시에만 실행되어야 한다.

그리고 ratation.z의 값이다. 이 값은 오일러 각도가 아니라 Quaternion의 z 요소를 나타내기 때문에 오일러 각도를 나타내는 rotation.eulerAngles.z 를 사용해야 한다. 

 

 

 

해결 완료!

 

 

회고


Castle의 공격과 원거리 적을 구현했다. Castle의 경우, 원래는 가장 가까운 적에게 활을 쏘는 것으로 구현하려고 했는데, 적의 Position으로 포물선 운동을 구현해도 화살이 날아가는 동안 적이 움직이기 때문에 명중을 하지 못한다고 생각을 해서 결국에는 좌우로 한 번씩, 일정 범위로 화살을 쏘는 것으로 구현했다. 그리고 원거리 적의 경우 기존에 구현했던 적 상태패턴에서 enum을 추가해서 공격 부분만 적용을 해서 구현했다. 트러블 슈팅에 작성한 것 처럼 생각보다 Castle의 포물선 운동을 구현하는데 시간이 꽤 걸렸다. 잘 정리해 두고 다음번에는 실수 없이 구현할 수 있을 것 같다!