Пример #1
0
    private void FixedUpdate()
    {
        if (IsDead)
        {
            return;
        }

        // 공격 시작 또는 공격 중일 경우, 대상을 향해 Y축을 기준으로 회전시킨다.
        if (state == State.AttackBegin || state == State.Attacking)
        {
            float targetAngleY = Quaternion.LookRotation(targetEntity.transform.position - transform.position).eulerAngles.y;

            targetAngleY          = Mathf.SmoothDamp(transform.eulerAngles.y, targetAngleY, ref turnSmoothVelocity, turnSmoothTime);
            transform.eulerAngles = Vector3.up * targetAngleY;
        }

        // 공격 중이라면, 공격범위 내 적들을 감지하여 공격 대상일 경우 데미지 처리를 한다.
        if (state == State.Attacking)
        {
            Vector3 dir           = transform.forward;
            float   deltaDistance = agent.velocity.magnitude * Time.deltaTime;

            // Physics.OverlapSphere는 해당 범위가 너무 빨리 움직일 경우 이동 경로에 있는 오브젝트가 감지되지 않는 경우가 있다.
            // SphereCast 사용 시 시작 지점과 끝 방향을 입력하여, 해당 경로로 구(sphere)가 이동한다고 가정하여 경로상의 모든 오브젝트를 감지한다.
            //  * NonAlloc: 감지된 물체의 RaycastHit 배열을 반환하지 않고 우리가 입력해준 배열을 사용한다. 배열에 입력된 원소 개수를 반환한다.
            //      ㄴ 매 프레임 배열을 새로 만드는 작업을 하지 않아도 되어 메모리에 이점이 있다. 참조 타입인 배열을 입력하므로 ref는 필요없음.
            int hitCount = Physics.SphereCastNonAlloc(attackRoot.position, attackRadius, dir, hits, deltaDistance, whatIsTarget);

            for (int i = 0; i < hitCount; i++)
            {
                LivingEntity hitEntity = hits[i].collider.GetComponent <LivingEntity>();

                if (hitEntity != null && !lastAttackedTargets.Contains(hitEntity))
                {
                    DamageMessage dmg = new DamageMessage();
                    dmg.amount    = _damage;
                    dmg.attacker  = gameObject;
                    dmg.hitNormal = hits[i].normal;

                    // SphereCast가 시작되는 프레임에서 바로 겹쳐있는 대상이 있다면, 거리 및 위치값이 0으로 나온다.
                    // 따라서 이런 경우 타격 지점은 0이 아니라 이 오브젝트의 공격 지점으로 설정해준다.
                    dmg.hitPoint = (hits[i].distance <= 0f) ? attackRoot.position : hits[i].point;

                    hitEntity.ApplyDamage(dmg);
                    lastAttackedTargets.Add(hitEntity);
                    break;
                }
            }
        }
    }