게임클라이언트 프로그래밍/R&D

Bullet Pattern R&D(Rush pattern)

Game Client Lee Hwanguk 2023. 3. 22. 08:54

#target을 향해 돌진 공격을 하는
보스 공격 패턴을 구현
#돌진 후 타겟 위치에서 범위 공격

*레퍼런스 영상

https://youtu.be/4FqJcTjoew0


#타겟 위치로 돌진

public class BossAttack : MonoBehaviour
{
    public GameObject target;
    public float attackInterval;
    public float attackDuration;
    public float attackSpeed;

    private LineRenderer lineRenderer;
    private Vector3 attackDirection;

    private float timeSinceLastAttack = 0f;
    private bool isAttacking = false;

    void Start()
    {
        lineRenderer = GetComponent<LineRenderer>();
    }

    void Update()
    {
        timeSinceLastAttack += Time.deltaTime;

        if (!isAttacking && timeSinceLastAttack > attackInterval)
        {
            StartAttack();
        }

        if (isAttacking && timeSinceLastAttack > attackDuration)
        {
            StopAttack();
        }
    }

    void StartAttack()
    {
        timeSinceLastAttack = 0f;
        isAttacking = true;

        Vector3 targetPosition = target.transform.position;
        attackDirection = (targetPosition - transform.position).normalized;

        // 예상 경로를 보여주기 위해 LineRenderer를 활성화합니다.
        lineRenderer.enabled = true;
        lineRenderer.positionCount = 2;
        lineRenderer.SetPosition(0, transform.position);

        StartCoroutine(AttackCoroutine());
    }

    void StopAttack()
    {
        isAttacking = false;

        // LineRenderer를 비활성화
        lineRenderer.enabled = false;

        // 타겟 위치로 돌진
        transform.position = target.transform.position;
    }

    IEnumerator AttackCoroutine()
    {
        float elapsed = 0f;
        while (elapsed < attackDuration)
        {
            // 예상 경로를 보여주기 위해 LineRenderer에 경로를 추가
            lineRenderer.SetPosition(1, transform.position + attackDirection * attackSpeed * elapsed);
            elapsed += Time.deltaTime;
            yield return null;
        }

        StopAttack();
    }
}

#돌진 후 지나간 경로에 범위데미지

public class Boss : MonoBehaviour
{
    public Transform target;             // 플레이어의 위치
    public float attackSpeed = 5f;       // 돌진 속도
    public float attackDuration = 3f;    // 돌진 시간
    public float attackCooldown = 5f;    // 공격 쿨타임
    public float attackRange = 2f;       // 범위 공격 범위

    private LineRenderer lineRenderer;   // 예상 경로를 보여주는 라인 렌더러 컴포넌트
    private bool isAttacking = false;    // 보스가 공격 중인지 여부
    private float timeSinceLastAttack;   // 마지막 공격 이후 흐른 시간

    void Start()
    {
        lineRenderer = GetComponent<LineRenderer>();
        lineRenderer.enabled = false;
    }

    void Update()
    {
        if (!isAttacking && timeSinceLastAttack >= attackCooldown)
        {
            StartAttack();
        }
        else if (isAttacking)
        {
            float elapsed = Time.time - startTime;
            transform.position += attackDirection * attackSpeed * elapsed;

            if (elapsed >= attackDuration)
            {
                StopAttack();
            }
        }
        else
        {
            timeSinceLastAttack += Time.deltaTime;
        }
    }

    void StartAttack()
    {
        // 타겟 위치로 이동하는 방향 계산
        Vector3 attackDirection = (target.position - transform.position).normalized;

        // 라인 렌더러 활성화 및 시작점, 끝점 설정
        lineRenderer.enabled = true;
        lineRenderer.SetPosition(0, transform.position);
        lineRenderer.SetPosition(1, transform.position + attackDirection * attackSpeed * attackDuration);

        // 공격 시작
        isAttacking = true;
        startTime = Time.time;

        // 공격 이후 일정 시간 후에 다시 공격 가능
        timeSinceLastAttack = 0f;

        // 범위 공격 코루틴 시작
        StartCoroutine(DoRangeAttack(lineRenderer.GetPositions()));
    }

    IEnumerator DoRangeAttack(Vector3[] path)
    {
        yield return new WaitForSeconds(attackDuration);

        // 경로 상에 있는 모든 적에게 범위 공격
        foreach (Collider2D collider in Physics2D.OverlapCircleAll(transform.position, attackRange))
        {
            if (collider.CompareTag("Player"))
            {
                // 적에게 데미지를 준다
                Player player = collider.GetComponent<Player>();
                player by.TakeDamage(10);
            }
        }
    }

    void StopAttack()
    {
        // 라인 렌더러 비활성화
        lineRenderer.enabled = false;

        // 타겟 위치로 이동
        transform.position = target.position;

        // 공격 종료
        isAttacking = false;
    }
}


https://docs.unity3d.com/ScriptReference/Physics2D.OverlapCircleAll.html

 

Unity - Scripting API: Physics2D.OverlapCircleAll

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

*physics2D.OverlapCircleAll을 통해 범위 안 모든 타겟 체크