지상 몹 중 하나인 스파이더는 머리의 y축이 회전된다.
그 덕에 좌우를 살필 수 있다.
하지만 플레이어가 점프하고 호버링을 해버리면 플레이어를 노리지 못한다.
그래서 머리의 양 옆에 달려있는 총구의 x축을 회전시켜주었다.
(급하게 찍느라 직접 움직이는 것을 찍었지만 인게임에서도 아주아주 잘 된다.)
아래는 코드
Quaternion currentLocalRotation = _weapon.localRotation;
_weapon.localRotation = Quaternion.identity;
Vector3 targetWorldLookDir = Target.position - _weapon.position;
Vector3 targetLocalLookDir = _weapon.InverseTransformDirection(targetWorldLookDir);
Quaternion targetLocalRotation = Quaternion.LookRotation(targetLocalLookDir, Vector3.up);
// Quaternion -> Euler
Vector3 euler = targetLocalRotation.eulerAngles;
euler.x = 0;
euler.z = 0;
// Euler -> Quaternion
targetLocalRotation = Quaternion.Euler(euler);
_weapon.localRotation = Quaternion.Slerp(
currentLocalRotation,
targetLocalRotation,
1 - Mathf.Exp(-Entity.Stat.rotationSpeed * Time.deltaTime)
);
몹 스폰을 공중에서 바닥으로 레이를 쏴서 닿는 곳으로 하면 y값이 0이 나온다.
스폰 위치의 y값이 0이 되면 생기는 문제 중 하나는 스폰된 몹이 바닥을 뚫고 나락으로 떨어져버리는 경우가 발생하는 것이다.
"아.. 이래서 내가 하던 게임에서 몬스터가 살짝 위쪽에서 생성되는 모습을 보였구나..!"
나도 감지된 스폰 위치에서 조금 위쪽으로 스폰 위치를 옮겨주는 작업을 했다. 감지된 부분에서 y값을 조금 높게 조정해주었다.
아래는 코드이고 맨 밑에서 살짝 올라가면
_groundTempPoint.Add(hit.point + Vector3.up * 3);
y값을 조정해주는 것을 볼 수 있음.
public void DetectSpawnPoint()
{
_groundTempPoint.Clear();
_groundSpawnPoints.Clear();
int groundLayer = LayerMask.GetMask("Ground");
int allLayers = LayerMask.GetMask("Ground", "Wall", "Unwalkable");
RaycastHit hit;
foreach (Vector3 cell in _groundCell)
{
if (Physics.Raycast(cell, Vector3.down, out hit, 41f, groundLayer))
{
Collider[] hitColliders = Physics.OverlapSphere(hit.point, cellRadius, allLayers);
bool onlyGround = true;
foreach (var hitCollider in hitColliders)
{
if (hitCollider.gameObject.layer != LayerMask.NameToLayer("Ground"))
{
onlyGround = false;
break;
}
}
if (onlyGround && hit.point.y <= 0.1f)
{
_groundTempPoint.Add(hit.point + Vector3.up * 3);
}
}
}
_groundSpawnPoints = new Queue<Vector3>(_groundTempPoint);
}
2계층 -> 3계층으로 변경하였다.
기존에는
Root : Alive -> Dead
Sub : Chasing / Phase1 -> Phase2
변경 후에는
Root : Alive -> Dead
Sub : NonCombat <-> Combat
Sub of Sub : Chasing / Phase1 -> Phase2 -> Phase3
Ball에 날라가는 오브젝트를 걸러주는 작업을 했다.
감지된 오브젝트에게서 Entity 컴포넌트만 받아와서 그 오브젝트의 강체를 가져오도록 했다.
private void Explosion()
{
RaycastHit[] hits = Physics.SphereCastAll(Context.Entity.transform.position, 10, Vector3.up, 0f);
foreach (RaycastHit hit in hits)
{
if (hit.transform.gameObject.TryGetComponent(out Entity entity))
{
Rigidbody rigidbody = entity.transform.GetComponent<Rigidbody>();
if (rigidbody != null)
{
Vector3 other = hit.transform.position;
Vector3 pushDirection = (other - _entityTransform.position).normalized;
rigidbody.AddForce(pushDirection * 20, ForceMode.Impulse);
rigidbody.AddForce(Vector3.up * 20, ForceMode.Impulse);
}
}
,,,생략,,,
}
,,,생략,,,
}
이 GIF는 볼때마다 뭔가 기분 좋다.