Unity/2D RPG

캐릭터(슬라임) by Unity

YunSeong 2021. 7. 18. 01:03
728x90
반응형

 

슬라임 타입의 적이 텍스쳐를 그리기에도 쉽기에 슬라임 타입의 적을 만들기로 했다. 

 

 

먼저 슬라임은 기본적으로 계속 점프를 하고 player을 발견하면 더 높고 빠르게 뛰도록 할 것이다. 

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
int Direction = 0;
 
Vector2 pos = new Vector2(transform.position.x, transform.position.y);
Vector2 boxSize = new Vector2(10.0f, 10.0f);
Collider2D[] collider2Ds = Physics2D.OverlapBoxAll(pos, boxSize, 0);
foreach (Collider2D collider in collider2Ds)
{
    if (collider.tag == "Player")
    {
        if ((transform.position.x - player.position.x) > 0) Direction = -1;
        if ((transform.position.x - player.position.x) < 0) Direction = 1;
    }
}
cs

일단 Physics2D.OverlapBoxAll()을 이용해서 위치는 pos이고 크기는 boxSize인 상자 안에 들어오는 모든 충돌체를 foreach문과 if문을 사용해서 tag를 조사해서 player인지 찾아낸다. 그리고 슬라임의 x좌표와 player의 x좌표를 비교해서 슬라임의 진행, 시선 방향을 1, -1을 이용해서 Direction 변수에 저장한다.

 

 

 

 

 

 

 

 

1
2
3
4
5
if (Direction != 0)
{
    float scale = transform.localScale.z;
    transform.localScale = new Vector3(Direction * -1 * scale, scale, scale);
}
cs

Direction에 따라서 localScale을 바꿔서 바라보는 방향을 자연스럽게 만들어준다. 

slime의 크기를 바꾸는 것을 쉽게 하기 위해서 scale을 localScale.z로 추출해서 사용했다. 

 

 

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
float coolTime = 3;
float curTime;
 
if (curTime > 0) curTime -= Time.deltaTime;
 
if (curTime <= 0)
{
    curTime = coolTime;
   jump();
}
else
{
    if (Direction == 0)
    {
        if (lastSpeedx > 0)
        {
            Direction = 1;
        }
        else if (lastSpeedx < 0)
        {
            Direction = -1;
        }
    }
 
    GetComponent<Rigidbody2D>().velocity = new Vector2(Speedx * 0.7f * Direction, GetComponent<Rigidbody2D>().velocity.y);
}
 
lastSpeedx = GetComponent<Rigidbody2D>().velocity.x; 
cs

curTime, coolTime을 이용해서 쿨타임이 돌 때마다 jump() 함수를 실행하게 한다. 쿨타임이 돌기 전일 때 Direction이 0이라면 위에서 player이 범위 안에 없던 것이기에 한 프레임 전의 방향에 따라서 계속 움직이도록 했다. 그리고 속도에 0.7f를 곱해줘서 느리게 움직이게 한다. 그리고 그 후에 다음 프레임에서 방향을 정하는데 도움을 주기 위해서 lastSpeedx를 

다시 설정해준다. jump() 함수는 밑에서 정의하겠다. 

 

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void jump()
{
    if(isGround())
    {
        GetComponent<Animator>().SetTrigger("tryJump");
        StartCoroutine(jumping());
    }
}
 
IEnumerator jumping()
{
    yield return new WaitForSeconds(0.35f);
 
    if (this.Direction != 0)
    {
        GetComponent<Rigidbody2D>().velocity = new Vector2(Speedx * this.Direction, Speedy);
    }
    else
    {
        GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, Speedy * 0.9f);
    }
}
cs

위 코드의 isGround() 함수를 정의하는 것은 밑에서 하고 일단 이 함수를 통해서 이 오브젝트가 땅에 있다면 밑 Trigger와 coroutine을 실행시키게 한다. coroutine을 사용하는 이유는 animation에서 슬라임이 점프를 뛰려고 준비하는 동작을 하고 나서 실제로 점프를 해야 하기 때문이다. 

 

그리고 실제 coroutine 함수에서는 시간의 딜레이를 주고 위에서 정의했던 변수인 Direction에 저장된 값에 따라서 속도를 설정하게 된다. 

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool isGround()
{
    Vector2 pos = new Vector2(transform.position.x, transform.position.y - 0.8f);
    Vector2 boxSize = new Vector2(0.2f, 0.2f);
 
    Collider2D[] collider2Ds = Physics2D.OverlapBoxAll(pos, boxSize, 0);
    foreach (Collider2D collider in collider2Ds)
    {
        if (collider != this.GetComponent<PolygonCollider2D>() && collider != this.GetComponent<CapsuleCollider2D>()) //슬라임 자신의 충돌체는 제외함
        {
            return true;
        }
    }
    return false;
}
cs

isGround() 함수는 적당한 posd와 boxSize를 정해서 그 상자가 슬라임의 바로 밑에 있게 하고 

OverlapBoxAll을 이용해서 그 상자에 들어오는 모든 충돌체를 검사해서 슬라임 자신의 충돌체는 if문을 이용해서 걸러야 한다. 그렇게 자신의 충돌체 제외한 충돌체가 들어오면 true를 반환하게 하고 아니면 false를 반환하게 하면 간단하게 

오브젝트가 바닥에 닿아있는지에 대한 정보를 알 수 있는 함수를 만들 수 있다.

 

 

 

점점 코드가 비효율적으로 짜지는 거 같다 언제 한번 다시 효율적으로 작동하게 코드를 손봐야겠다. 

 

 

 

 

 

728x90
반응형

'Unity > 2D RPG' 카테고리의 다른 글

캐릭터(원거리 공격) byUnity  (0) 2021.07.24
회복 아이템 by Unity  (0) 2021.07.18
원거리 공격 by Unity  (0) 2021.07.14
카메라 무빙 by Unity  (0) 2021.07.08
근접 공격 by Unity  (0) 2021.07.07