Ch 7. 스테이지 구현(+ Snap Settings)
카테고리: Unity Lesson 4
태그: Unity Game Engine
케이디님의 [유니티 강좌] 리듬 게임 유튜브 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click
🚀 스테이지 구현
납작한 큐브 만들어서 텍스처 입히기
✈ 머테리얼에 텍스처 입히기
머테리얼에 텍스처를 입히려면 머테리얼의 Albedo
왼쪽에 있는 조그마한 네모에 텍스처 파일을 드래그 앤 드롭 하면 된다. 이 머테리얼을 큐브에 입혀 플레이트 프리팹을 만든다.
✈ Gird and Snap Settings
오브젝트를 정밀하게 말고 어떤 단위로 딱딱 이동시키려면 Ctrl
을 누른 상태에서 오브젝트를 이동시키면 된다. (이걸 Snap 이라고 하는 것 같다.) 위 플레이트의 길이는 1 이기 때문에 플레이트 오브젝트들을 옮겨서 배치하려고 할 떄 Ctrl
을 누른 상태에서 1 씩 이동되게끔 하고 싶다면
Edit - Grid and Snap Settings 에서 Move 부분을 1 로 설정해주면 된다. 이제 스냅으로 오브젝트를 이동시킬 때 1 단위로 움직이게 하기 떄문에 배치하기가 편해진다.
Stage
👉 📜StageManagerStage1
,Stage2
… 👉 📜Stage (Stage 들)- 각 스테이지에 속한
Plate
들 👉📜BasicPlate, 태그도 “BasicPlate”
- 각 스테이지에 속한
🚀 스테이지 스크립트
📜BasicPlate
public class BasicPlate : MonoBehaviour
{
public bool flag = true;
}
이미 밟았던 플레이트라면 false
로 바꿀 것.
첫 번째 플레이트는 시작 플레이트니까 false
로.
📜Stage
public class Stage : MonoBehaviour
{
public Transform[] plates;
}
한 스테이지마다 저장해둘 “게임 중 밟으면 활성화 상태로 바꿀” 플레이트들 plated
📜 StageManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StageManager : MonoBehaviour
{
[SerializeField] GameObject stage = null;
Transform[] stagePlates;
[SerializeField] float offsetY = -3; // 플레이트 활성화시 밑에서 올라오게 할거라..
[SerializeField] float plateSpeed = 10; // 플레이트 활성화시 올라오는 속도
int stepCount = 0;
int totalPlateCount = 0; // stepCount가 stagePlates.Length를 넘으면 안된다.(배열 인덱스 범위 초과 에러 막기 위해)
void Start()
{
stagePlates = stage.GetComponent<Stage>().plates;
totalPlateCount = stagePlates.Length;
// 플레이트들 밑에서 올라오면서 활성화 되도록 offset 만큼 밑에 위치하도록 세팅 (현재 비활성화 상태)
for (int i = 0; i < totalPlateCount; i++)
{
stagePlates[i].position = new Vector3(stagePlates[i].position.x,
stagePlates[i].position.y + offsetY,
stagePlates[i].position.z);
}
}
public void ShowNextPlate()
{
if (stepCount < totalPlateCount)
StartCoroutine(MovePlateCo(stepCount++));
}
// 플레이트를 활성화 하고 코루틴으로 천천히 부드럽게 위로 올라 오게 함
IEnumerator MovePlateCo(int p_num)
{
stagePlates[p_num].gameObject.SetActive(true);
Vector3 t_destPos = new Vector3(stagePlates[p_num].position.x,
stagePlates[p_num].position.y - offsetY,
stagePlates[p_num].position.z);
while(Vector3.SqrMagnitude(stagePlates[p_num].position - t_destPos) >= 0.001f)
{
stagePlates[p_num].position = Vector3.Lerp(stagePlates[p_num].position, t_destPos, plateSpeed * Time.deltaTime);
yield return null;
}
stagePlates[p_num].position = t_destPos;
}
}
📜 PlayerController
public Vector3 destPos = new Vector3();
void Update()
{
if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.D) ||
Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.S))
{
if (canMove)
{
Calc();
// 판정 체크 : Perfect, Cool, Good, Bad 일 때만 True
if (theTimingManager.CheckTiming())
{
StartAction();
}
}
}
}
void Calc()
{
// 큐브의 x축 -> 위 아래 큐브의 z축 -> 오른쪽, 왼쪽
dir.Set(Input.GetAxisRaw("Vertical"), 0, Input.GetAxisRaw("Horizontal"));
// 이동 목표값 게산
destPos = transform.position + new Vector3(-dir.x, 0, dir.z);
// 회전 목표값 계산
rotDir = new Vector3(-dir.z, 0f, -dir.x);
fakeCube.RotateAround(transform.position, rotDir, spinSpeed); //공전
destRot = fakeCube.rotation;
}
void StartAction()
{
StartCoroutine(MoveCo());
StartCoroutine(SpinCo());
StartCoroutine(RecoilCo());
StartCoroutine(theCam.ZoomCam());
}
📜 TimingManager
StageManager theStage;
PlayerController thePlayer;
theStage = FindObjectOfType<StageManager>();
thePlayer = FindObjectOfType<PlayerController>();
// 이 함수가 True 를 리턴할 때 플레이트를 활성화 하고 점수를 증가시킬 것!
// 플레이어의 목표 위치에 이미 플레이트가 있다면(Raycast 걸리는게 BasicPlate라면) flag 를 True 로 만들고 true 리턴.
bool CheckCanNextPlate()
{
if (Physics.Raycast(thePlayer.destPos, Vector3.down, out RaycastHit t_hitInfo, 1.1f))
{
if (t_hitInfo.transform.CompareTag("BasicPlate"))
{
BasicPlate t_plate = t_hitInfo.transform.GetComponent<BasicPlate>();
if (t_plate.flag)
{
t_plate.flag = false;
return true;
}
}
}
return false;
}
public bool CheckTiming()
{
//...
if (CheckCanNextPlate())
{
theScoreManager.IncreaseScore(j); // 점수 증가
theStage.ShowNextPlate(); // 다음 플레이트 호출
theEffect.JudgementEffect(j);
}
else
{
// Normal 이미지 뜨게끔. 점수 반영도 X
theEffect.JudgementEffect(5);
}
return true;
}
}
}
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기