2023. 11. 2. 18:19ㆍSKKU DT
<평면 위에 캐릭터 돌아다니면서 아이템 먹으면 점수 올라가는 게임>
캐릭터 움직이기 위한 Inpuit Manager 먼저 확인 (기본 18개, 추가 가능)
플레이어 움직이게 하는 스크립트 작성 (+플레이어에 스크립트 컴포넌트 추가)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour
{
public float speed = 5f;
void Start()
{
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
//콘솔 창 디버그 로그 확인
Debug.Log("h: " + horizontal);
Debug.Log("v: " + vertical);
//거리 = 속도 * 시간
horizontal = horizontal * speed * Time.deltaTime;
vertical = vertical * speed * Time.deltaTime;
//이동
transform.Translate(horizontal * Vector3.right);
transform.Translate(vertical * Vector3.forward);
}
}
카메라가 플레이어를 따라다니게 하기 (카메라에 스크립트 컴포넌트 추가)
(***플레이어와 카메라 사이의 거리를 구한 다음 플레이어가 움직일 때 거리를 계속해서 업데이트)
(거리 d = 카메라의 위치 c - 플레이어의 위치 p, 카메라의 위치 c = 플레이어의 위치 p + 거리 d)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControl : MonoBehaviour
{
public GameObject player;
Vector3 distance; //카메라와 플레이어 사이의 거리 변수
void Start()
{
distance = transform.position - player.transform.position;
}
void Update()
{
transform.position = player.transform.position + distance;
}
}
**카메라가 버벅거리는 현상 발생 -> 플레이어와 카메라의 Update가 순서가 정해져있지 않기 때문.
-> FixedUpdate, Update, LateUpdate의 차이로 해결 가능.
LateUpdate : Update가 끝난 후 프레임당 한 번 호출. 주로 3인칭 카메라에 사용된다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControl : MonoBehaviour
{
public GameObject player;
Vector3 distance; //카메라와 플레이어 사이의 거리 변수
void Start()
{
distance = transform.position - player.transform.position;
}
void LateUpdate()
{
transform.position = player.transform.position + distance;
}
}
플레이어 회전 막기 -Rigid Body -Rotation constraints
아이템 만들기, 먹어서 없애기 - CallBack 이벤트 함수(On으로 시작하는) 필요 (OnCollisionEnter는 Trigger 아닐 때 충돌 감지 / OnTriggerEnter는 Trigger 감지)
방법 1. Hierarchy 창엔 있지만 비활성화 시키기(v)
방법 2. Hierarchy 창에서도 아예 삭제하기
Prefab 사용
그냥 복제와 Prefab 사용의 차이: 프리팹 내부로 들어가서 메테리얼 변경하면 다른 프리팹까지 같이 바뀐다.
Item 프리팹에 Tag 달기(item인 것만 먹기 위해서)
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("item"))
{
Debug.Log("트리거 감지");
other.gameObject.SetActive(false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VFX;
public class PlayerControl : MonoBehaviour
{
public float speed = 5f;
void Start()
{
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
//콘솔 창 디버그 로그 확인
//Debug.Log("h: " + horizontal);
//Debug.Log("v: " + vertical);
//거리 = 속도 * 시간
horizontal = horizontal * speed * Time.deltaTime;
vertical = vertical * speed * Time.deltaTime;
//이동
transform.Translate(horizontal * Vector3.right);
transform.Translate(vertical * Vector3.forward);
}
private void OnCollisionEnter(Collision collision) //괄호 안은 Argument
{
Debug.Log("충돌 감지");
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Item"))
{
Debug.Log("트리거 감지");
other.gameObject.SetActive(false);
}
}
}
점수 올리기
-int count; 추가해서 트리거 감지되면 로그 창에 +10점 씩 추가 되는 걸로.
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Item"))
{
other.gameObject.SetActive(false); //아이템 비활성화
count += 10;
print("Score: " + count);
}
}
UI -점수 표시, 게임 재시작 등 메뉴
Screen Space -Overlay: 무조건 스크린에서만 2차원으로 고정되어 있다고 생각하면 됨. 독립적으로 움직인다.
Screen Space -Camera: 카메라의 Fov를 따라간다. 게임 뷰 위에 캔버스가 올려져 있는 듯.
이미지와 텍스트 생성 후 PlayerControl 스크립트 수정
using TMPro; 추가
TextPro에서 텍스트를 가져오기
public TextMeshProUGUI scoreText;
새 함수 만들기 void SetCount()
void SetCount()
{
scoreText.text = "Score: " + score.ToString(); //ToString()으로 문자열로 바꾸기
}
만든 함수를 void Start();에 추가
void Start()
{
score = 0;
SetCount();
}
OnTriggerEnter 함수 안에 추가
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Item"))
{
//Debug.Log("트리거 감지");
other.gameObject.SetActive(false); //아이템 비활성화
score += 10;
Destroy(other.gameObject);
SetCount();
}
}
ScoreText 추가
전체 PlayerControl 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerControl : MonoBehaviour
{
public float speed = 5f;
int score;
public TextMeshProUGUI scoreText;
void Start()
{
score = 0;
SetCount();
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
//콘솔 창 디버그 로그 확인
//Debug.Log("h: " + horizontal);
//Debug.Log("v: " + vertical);
//거리 = 속도 * 시간
horizontal = horizontal * speed * Time.deltaTime;
vertical = vertical * speed * Time.deltaTime;
//이동
transform.Translate(horizontal * Vector3.right);
transform.Translate(vertical * Vector3.forward);
}
private void OnCollisionEnter(Collision collision) //괄호 안은 Argument
{
Debug.Log("충돌 감지");
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Item"))
{
//Debug.Log("트리거 감지");
other.gameObject.SetActive(false); //아이템 비활성화
score += 10;
SetCount();
}
}
void SetCount()
{
scoreText.text = "Score: " + score.ToString(); //ToString()으로 문자열로 바꾸기
}
}
일정 점수 이상이면 Game Clear 텍스트 활성화
텍스트 생성 후
GameObject public 변수 생성
public GameObject clearText;
Start 함수에서 초기에 비활성화
void Start()
{
score = 0;
SetCount();
clearText.SetActive(false);
}
SetCount() 함수에서 다 먹으면 true로 변경
void SetCount()
{
scoreText.text = "Score: " + score.ToString(); //ToString()으로 문자열로 바꾸기
if(score >= 200) //점수가 일정 이상이면
{
clearText.SetActive(true); //Game Clear 텍스트 활성화
}
}
메뉴 패널 만들기
패널 추가
GameClear 텍스트는 패널의 자식으로 넣는다.
패널의 자식으로 버튼 2개 생성.
ClearText 부분에 Panel 전체 드래그해서 한번에 뜨게 한다.
GameManager 스크립트 생성
GameManager 스크립트에 using UnityEngine.SceneManagement; 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public void RestartGame() //버튼에서 불러올 것이기 때문에 public 붙인다. 버튼에 연결이 되는 함수
{
//활성화 되어있는 씬을 다시 불러온다
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
Time.timeScale = 1.0f; //일시정지 해제
}
public void QuitGame()
{
Application.Quit(); //실행 말고 빌드에서만 작동함
}
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
버튼에 함수 매핑
아이템 랜덤 생성 PlayerControl Script 최
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerControl : MonoBehaviour
{
//필드 선언 스피드, 스코어, UI텍스트
public float speed = 5.0f;
int score;
public TextMeshProUGUI scoreText;
public GameObject clearText;
//랜덤 생성을 위한 변수 선언 스폰타임, 스폰스피드, float 타임, 복제를 위한 item
float spawntime = 3;
float spawnSpeed;
public float time = 0;
public GameObject item;
void Start()
{
score = 0; //스코어 초기확
SetCount(); //SetCount 함수 실행
clearText.SetActive(false); //GameClear 텍스트 비활성화
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
//콘솔 창 디버그 로그 확인
//Debug.Log("h: " + horizontal);
//Debug.Log("v: " + vertical);
//거리 = 속도 * 시간 -> 변수에 대입
horizontal = horizontal * speed * Time.deltaTime;
vertical = vertical * speed * Time.deltaTime;
//이동
transform.Translate(horizontal * Vector3.right);
transform.Translate(vertical * Vector3.forward);
//이동 제한
float nowX = transform.position.x;
float nowZ = transform.position.z;
if(nowX < -10)
{
nowX = -10;
}
if (nowX > 10)
{
nowX = 10;
}
if (nowZ < -10)
{
nowZ = -10;
}
if (nowZ > 10)
{
nowZ = 10;
}
transform.position = new Vector3(nowX, 0.5f, nowZ);
//랜덤 출현
spawnSpeed = Random.Range(1.0f, 5.0f);
time += Time.deltaTime * spawnSpeed;
if(time > spawntime)
{
time = 0;
Instantiate(item, new Vector3(Random.Range(-9.0f, 9.0f), 0.25f, Random.Range(-9.0f, 9.0f)), Quaternion.identity);
item.gameObject.SetActive(true);
}
}
private void OnCollisionEnter(Collision collision) //괄호 안은 Argument
{
if (collision.gameObject.CompareTag("Obstacle"))
{
Debug.Log("충돌 감지");
MeshRenderer mesh = collision.gameObject.GetComponent<MeshRenderer>();
mesh.material.color = Color.red;
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Obstacle"))
{
MeshRenderer mesh = collision.gameObject.GetComponent<MeshRenderer>();
mesh.material.color = Color.green;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Item"))
{
//Debug.Log("트리거 감지");
other.gameObject.SetActive(false); //아이템 비활성화
score += 10;
Destroy(other.gameObject);
SetCount();
}
}
void SetCount()
{
scoreText.text = "Score: " + score.ToString(); //ToString()으로 문자열로 바꾸기
if(score >= 100) //점수가 일정 이상이면
{
clearText.SetActive(true); //Game Clear 텍스트 활성화
Time.timeScale = 0; //팝업이 뜨면서 게임 일시정지
}
}
}
완성
개발 방법론
병렬 형태 개선된 개발 방식
기획자가 아트, 프로그래머에게 각각 의견 전달 가능.
기획/프로그래밍/디자인
프로그램
- 클라이언트
-엔진 개발, 툴 개발, UI개발 - 서버
-네트워크(firebase, photon), DB, 보안
'SKKU DT' 카테고리의 다른 글
[SKKU DT] 7일차 - 3D 그래픽스 이론(Rasterize, 셰이더), 블렌더 포토샵으로 UV (0) | 2023.11.07 |
---|---|
[SKKU DT] 6일차 -3D 그래픽스 이론 / 블렌더 모델링 (0) | 2023.11.06 |
[SKKU DT] 5일차 -2D 기반 슈팅게임 만들기 (0) | 2023.11.03 |
[SKKU DT] 3일차 -유니티 기본(에셋, 메테리얼, 텍스쳐, 애니메이션), C# 기본 (0) | 2023.11.01 |
[SKKU DT] 2일차 메모 -디지털 트윈 서적, RFP (0) | 2023.10.31 |