유니티 게임 개발/Jumping Rabbit

[유니티] Jumping Rabbit #5 모바일 UI와 하드모드 구현

노랑꼬리 2022. 11. 18. 23:20

※ 구현목표

모바일 조작 버튼 UI와 하드모드 구현

01

1. 모바일 UI

1) 조작 버튼

모바일 UI는 이벤트 트리거를 사용하여 버튼 클릭시 Player 객체에서 함수에 값을 넣어주는 형식을 사용하였다.

 

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
29
30
31
32
  public void ButtonDown(string type)
  {
    switch (type)
    {
      case "J":
        Jump_Down = true;
        isClick = true;
        break;
      case "L":
        Left_Down = true;
        break;
      case "R":
        Right_Down = true;
        break;
    }
  }
  public void ButtonUp(string type)
  {
    switch (type)
    {
      case "J":
        Jump_Up = true;
        isClick = false;
        break;
      case "L":
        Left_Down = false;
        break;
      case "R":
        Right_Down = false;
        break;
    }
  }
cs

 

switch문을 사용하여 입력에 따라 현 입력 상태를 bool 값으로 처리하여 Player 클래스 내에서 동작 제어로 사용하였다.

버튼 내부에서 이벤트 트리거 컴포넌트를 사용하여 Player 객체의 Button 함수들의 입력을 정해주었다.

Jump 버튼을 누르면 J

왼쪽 버튼을 누르면 L

오른쪽 버튼을 누르면 R

 

2) 타이머


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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
 
public class Timer : MonoBehaviour
{
  public float GameTimer;
  public TextMeshProUGUI ClearTime;
 
  private void Awake()
  {
    ClearTime = GetComponent<TextMeshProUGUI>();
  }
  void Start()
  {
 
  }
 
  // Update is called once per frame
  void Update()
  {
    GameTimer += Time.deltaTime;
    ClearTime.text = (Mathf.Round(GameTimer * 10* 0.1f).ToString();
  }
}
 
cs

 

 

클리어 타임을 플레이어가 볼 수 있도록 UI로 제공해준다.

Update()는 1초당 프레임 수 만큼 동작한다.                      (ex. 60프레임이라면 1초에 60번 동작)

Time.deltaTime 은 프레임당 시간을 뜻한다.                                (ex. 60프레임 이라면 1/60)

 

즉, GameTimer는 1초당 1/60이 60번 동작하므로  1초에 1의 값이 올라 시간을 셀 수 있게 된다.

하지만 이 값은 1/60씩 오르기 때문에 (1/60 은 0.0166666666666667 이다)

소수점이 너무 많이 보여 사용자가 보기 불편하므로 Round 함수로 소수 첫째자리 까지만 보이도록 조정해주었다.

(*10 이후 *0.1f를 해주어 값은 동일하지만 소수 첫째 자리도 보이게 함)

조작 버튼과 같은 UI에 띄워준다.

2. 하드모드 구현

 

하드모드는 이지모드 맵에서 추격자(데스웜)과 추격자의 속도를 늦춰줄 바위를 추가해주었다.

 

1) 데스웜

데스웜이 아래서 올라오는 것을 구현하였다.

 

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
 
public class Chaser : MonoBehaviour
{
  Rigidbody2D rbody;
  SpriteRenderer sprite;
  public float DeathWormSpeed;
  public GameObject GameOverPanel;
  private float Move;
  private float MoveTimer;
  private float RageCount;
  private float StagePoint;
  AudioSource audioSource;
 
 
 
  void Start()
  {
    rbody = GetComponent<Rigidbody2D>();
    sprite = GetComponent<SpriteRenderer>();
    rbody.constraints = RigidbodyConstraints2D.FreezeRotation;
    audioSource = GetComponent<AudioSource>();
    GameOverPanel.SetActive(false);
    RageCount = 0;
    StagePoint = 1;
  }
 
  // Update is called once per frame
  void FixedUpdate()
  {
    MoveTimer += 0.01f;
    MoveRule();
    RageDown();
    transform.position += Vector3.up * DeathWormSpeed * 0.01f * Move;
  }
 
  void MoveRule()
  {
    if (MoveTimer >= 1)
    {
      Move = 0.1f;
      MoveTimer = 0;
    }
    else if (MoveTimer >= 0.5)
    {
      Move = 1;
    }
  }
  void TimeStop()
  {
    Time.timeScale = 0;
  }
  private void OnTriggerEnter2D(Collider2D collision)
  {
    if (collision.gameObject.tag == "Player")
    {
      Invoke("TimeStop"7);
      Handheld.Vibrate();
      GameOverPanel.SetActive(true);
    }
    if (collision.gameObject.tag == "Attack")
    {
      Destroy(collision.gameObject);
      DeathWormSpeed -= 2 * StagePoint;
      RageCount += 1;
      audioSource.Play();
      if (RageCount >= 3)
      {
        DeathWormSpeed = 6 * StagePoint;
        Handheld.Vibrate();
      }
      sprite.color = new Color(10.2f * (5 - RageCount), 0.2f * (5 - RageCount));
      Invoke("SpeedReset"4.0f);
    }
    if (collision.gameObject.tag == "Stage")
    {
      StagePoint += 0.1f;
      Destroy(collision.gameObject);
      DeathWormSpeed = 2 * StagePoint;
      Handheld.Vibrate();
      audioSource.Play();
    }
  }
 
  void SpeedReset()
  {
    DeathWormSpeed = 2 * StagePoint;
    sprite.color = new Color(10.2f * (5 - RageCount), 0.2f * (5 - RageCount));
  }
 
  void RageDown()
  {
    if (RageCount > 0.5f)
    {
      RageCount -= 0.005f;
    }
  }
}
 
 
 
cs

기능은 4가지로

 

주기적으로 상승과 정지를 반복하여 벌레가 움직이는 모습을 표현

스테이지가 넘어가면 StagePoint를 올려주어 데스웜의 속도를 증가

공격 당하면 잠시 스턴, 연속으로 맞으면 뒤로 물러남, 타격에 따라 색 변화

공격 당하면 분노수치 상승, 일정 수치를 넘기면 데스웜 속도 큰 폭으로 증가

 

 

2) 바위

Player와 접촉하면 돌이 바닥으로 떨어지는것을 구현하고자 했는데

중력값의 변경으로 조정할 경우 제대로 적용이 되지않고 무중력 상태로 떠다니는 문제가 있었다.

이를 해결하기 위해 Layer ("Stone")를 적용하여 플랫폼과 Player와의 물리 작용을 제외시켜주었다.

 

 

Player와 충돌 이전까지는 물리적용을 받지 않아야하는데 이를 위해 Stone 오브젝트들의 Rigidbody2D를 Kinematic으로 설정해준다.

Kinematic으로 설정되어있으면 물리엔진이 해당 오브젝트에 작동하지 않게된다.

 

 

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
29
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Stone : MonoBehaviour
{
  Rigidbody2D rbody;
  void Start()
  {
    rbody = GetComponent<Rigidbody2D>();
  }
 
  // Update is called once per frame
  void Update()
  {
 
  }
 
  private void OnCollisionEnter2D(Collision2D collision)
  {
    if (collision.gameObject.tag == "Player")
    {
      rbody.isKinematic = false;
      this.gameObject.tag = "Attack";
    }
  }
 
}
 
cs

Player와 접촉하면 Kinematic을 false로 해주므로서 기본형태인 Dynamic으로 돌아가고 돌은 추락하게 된다.