Unity, 2D, 플랫포머.
Enemy, Player, Wall으로 구성되어 있을 때, Enemy는 Player를 쫓아가면서 Wall을 뛰어넘어서 Player에게 다가가고 싶다.
private Rigidbody2D enemyRB;
private SpriteRenderer enemySprite;
Enemy, 즉 몬스터의 속도는 일정했으면 좋겠으므로, 움직이는 방식은 rigidbody의 velocity 값을 입력해서 구현해주도록 하자. 또, 왼쪽 오른쪽 움직일 때 스프라이트 방향이 달라지므로, SpriteRenderer도 받아와야 한다.
private void Awake()
{
enemyRB = GetComponent<Rigidbody2D>();
enemySprite = GetComponent<SpriteRenderer>();
}
Awake에서 이런 값들을 받아오도록 하자.
그 다음은 점프. rigidbody를 받아왔으니, 위로 Addforce하는 방식으로 점프를 구현해보자.
void Jump()
{
enemyRB.AddForce(jumpPower * Vector2.up, ForceMode2D.Impulse);
}
이제 이것으로 y축의 움직임은 끝. 아래로 떨어지는 것은 중력에 의해, 위로 올라가는 것은 점프로만 실행할 것이다.
그럼 x축의 움직임은 어떨까? 꽤 제약을 많이 받는 편이다. 다른 몬스터, 벽, 플레이어 등에 영향을 받기에, 움직일 수 있는 상황인지 아닌지에 대한 bool값을 줄 것이다.
void DetectMoveXTest()
{
Vector2 rayDirection = enemySprite.flipX ? Vector2.left : Vector2.right;
RaycastHit2D hit = Physics2D.Raycast(gameObject.transform.position, rayDirection, detectMoveXDistance, ~EnemyLayer);
if(hit.collider != null)
{
canMoveX = false;
}
else
{
canMoveX = true;
}
}
그런 상황을 테스트하는, DetectMoveXTest 코드가 아래와 같다.
rayDirection은 삼항 연산자를 사용하여 몬스터의 진행 방향이 오른쪽이면 오른쪽, 왼쪽이면 왼쪽을 가르킨다.
이 방향은 RaycastHit2D에 사용되어, 앞에 있는 물체를 찾는다.(단, ~EnemyLayer을 통해 같은 Enemy는 제외) 그래서 물체가 인식되면, canMoveX를 false로 반환한다.
DetectMoveXTest();
if (canMoveX)
{
Move();
}
else
{
Vector2 velocity = enemyRB.velocity;
velocity.x = 0;
enemyRB.velocity = velocity;
}
위는 Update의 구문으로, canMoveX가 true라면 움직이고, false라면 움직이지 않도록 x의 속도를 0으로 만들어 y의 이동만을 허용한다.
private void Move()
{
Vector2 velocity = enemyRB.velocity;
if (targetTransform.position.x > gameObject.transform.position.x)
{
//몬스터가 오른쪽으로 이동
enemySprite.flipX = false;
velocity.x = speed;
}
else
{
//몬스터가 왼쪽으로 이동
enemySprite.flipX = true;
velocity.x = -speed;
}
enemyRB.velocity = velocity;
}
Move()는 targer, 즉 플레이어의 위치가 몬스터보다 오른쪽에 있으면 오른쪽으로 이동하며 스프라이트가 정면을, 왼쪽에 있으면 왼쪽으로 이동하며 스프라이트가 뒤를 향하게 한다.
다음으로는 충돌을 찾는 것보다 조금 더 길게 RaycastHit2D를 사용하여, 앞에 벽이 있을 때 jump를 실행하는 코드이다.
void DetectJumpTest() //몬스터 앞에 있는 물체 확인
{
//물체 방향에 따른 감지 방향
Vector2 rayDirection = enemySprite.flipX ? Vector2.left : Vector2.right;
//enemyLayer을 제외하고 감지한다.
RaycastHit2D hit = Physics2D.Raycast(gameObject.transform.position, rayDirection, detectJumpDistance, ~EnemyLayer);
if (hit.collider != null)
{
//벽이면 점프
if (hit.collider.CompareTag("Wall"))
{
Jump();
}
//플레이어면 공격
if (hit.collider.CompareTag("Player"))
{
//Attack();
}
}
}
여기까지 진행했으면, 물체는 플레이어를 향해 이동하고, 벽을 앞에 두면 점프하여 플레이어를 향해 넘어간다.
※ 이때, Pivot값은 SpriteRenderer에서 꼭 설정을 해주도록 하자. 바닥으로 판정해야 나중에 편해진다.
여기까지 진행했으면 대부분의 기능은 완성되지만, 몬스터가 여럿 있을 때는 서로 충돌하여 버벅거리는데, 이것은 똑같은 Layer끼리 충돌하지 않도록 하면 해결되는 문제다(Project Setting에서 설정 가능)
'만들고 싶은 QnA' 카테고리의 다른 글
Q. Unity, 물체가 움직이다가 바닥에서 갑자기 튀어올라요. (0) | 2023.10.24 |
---|