지금 듣고 있는 곡 - DECO 27 / 毒占欲
특유의 리듬과 가사가 좋은 곡이다
1. 오늘 구현할 기능
참여 시간 18:20(PM 06:20)
-상점 버튼들 기능 추가 완료
-미연시 scence, 전투 scence를 메인 scence으로 이동(scence - scence 이동 방식을 카메라 전환으로 변경)
-하쿠레이 신사 청소 미니게임
2. 추후 구현할 기능
-홍마관 파츄리 플레쉬 암산 미니게임
상점 UI 를 완성했다
이제 버튼UI들에 기능을 추가해 보자
public float player_HP = 100;
public float maxHP = 100; //* 최대 체력
public float forced = 5;
public bool iswin = false;
public bool fightend = false;
기본 골자는 게임 매니저에 있는 변수의 값들을 추가해주는 방식으로 만들어야 한다
이때 사용되는 재화는 NPC매니저에 있는 변수
public int Gold = 0; // 골드
를 사용한다
이 변수들을 엮어서 버튼 기능을 구현한다
??? 이건 뭐야 내가 이딴 변수명을 왜쓴거지?
찾아보자
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player")) // 충돌한 객체가 enemy 태그를 가지고 있는 경우
{
// 오브젝트의 현재 방향으로 반대 방향으로 힘을 가합니다.
rb.AddForce(transform.right * backwardForce);
HP -= Gamemanager.Instance.forced;
}
}
적 오브젝트 스크립트에 들어있는 코드를 보니 공격력인가 보다
변수명을 수정한다
public void up_power()
{
if(NPCManager.Instance.Gold >= 10){
NPCManager.Instance.Gold -= 10;
Gamemanager.Instance.power += 1;
}
}
버튼 기능을 이렇게 넣어준다
public class Gold_text : MonoBehaviour
{
public TextMeshProUGUI Text;
void Start(){
Text.GetComponent<TextMeshProUGUI>();
}
void Update()
{
Text.text = NPCManager.Instance.Gold.ToString();
}
}
상점에서 골드를 표시할 텍스트를 위한 스크립트도 추가한다
이제 테스트를 해보자
이상없이 잘 된다
이제 골드가 부족할때 연출을 추가한다
대충 이런 이미지를 출력하도록 하자
스크립트는 전에 사용했던 골드 획득 스크립트를 재활용한다
public GameObject less_gold;
// Start is called before the first frame update
public void up_power()
{
if(NPCManager.Instance.Gold >= 10){
NPCManager.Instance.Gold -= 10;
Gamemanager.Instance.power += 1;
}
else if(NPCManager.Instance.Gold < 10){
less_gold.SetActive(true);
}
}
이제 버튼에 골드가 없을때 연출을 true로 변환하게 한다
되긴 되는데, 글자가 하얕게 뜬다
이전에 골드 획득 연출과 비슷한 상황이다
-----------------------------------------------
그냥 오브젝트 순서 문제였다
이제 방어력을 추가해야 하니 게임 매니저에 방어력 변수를 추가한다
public float defense = 0;
이에 따라 전투의 계산식도 변경한다
int damege = 5;
if(damege > Gamemanager.Instance.defense)
Gamemanager.Instance.player_HP -= 5 - Gamemanager.Instance.defense; // 일반 적
else if(damege <= Gamemanager.Instance.defense)
Gamemanager.Instance.player_HP -= 1;
이제 전투에 플레이어의 방어력이 적용된다
public void up_defense()
{
if(NPCManager.Instance.Gold >= 10){
NPCManager.Instance.Gold -= 10;
Gamemanager.Instance.defense += 1;
}
else if(NPCManager.Instance.Gold < 10){
less_gold.SetActive(true);
}
}
방여력 구입 버튼 기능도 똑같이 구현해 준다
이제 회피력을 구현하자
rand로 변수를 주사위를 굴려서 이상 - 이하 검사를 하면 된다
근데, 지금 전투씬을 메인씬으로 옮기는 작업을 하지 않았으니, 회피력 구입 버튼은 이후로 넘겨야 할 것 같다
public void up_dodge()
{
if(NPCManager.Instance.Gold >= 10){
NPCManager.Instance.Gold -= 10;
Gamemanager.Instance.dodge += 1;
}
else if(NPCManager.Instance.Gold < 10){
less_gold.SetActive(true);
}
}
일단은 코드로만 남겨두자
이제 전투씬을 메인씬으로 옮겨오자
벌써 막막하다....
애초에 씬이동으로 구현된거라 스크립트를 다시 짜야할 것 같다
대충 매커니즘만 가져오도록 하자
대충 세팅을 가져왔다
이제 메인씬에 맞추어 스크립트를 수정해 주어야 한다
우선, 월드에서 몬스터와 충돌시 원래는 씬 자체를 이동시켰는데, 이를 카메라 변경으로 수정해 주어야 한다
void ChangeScene()
{
// 씬을 변경하는 코드를 여기에 추가하세요.
// 예를 들어 SceneManager.LoadScene()을 사용할 수 있습니다.
SceneManager.LoadScene("Fight");
}
원래는 이 함수를 이용해서 이동하는데, 이를 카메라 매니저를 사용하는 방식으로 수정해야 한다
이를 구현하기 위해서 카메라 매니저 스크립트를 수정하자
public Camera camera1;
public Camera camera2;
public int isCamera1Active = 1;
void Start()
{
camera1.enabled = true;
camera2.enabled = false;
}
void Update()
{
if(isCamera1Active == 1){
camera1.enabled = true;
camera2.enabled = false;
}
else if(isCamera1Active == 2){
camera1.enabled = false;
camera2.enabled = true;
}
}
여기에 카메라 1개를 더 추가해 준다
void Start()
{
camera1.enabled = true;
camera2.enabled = false;
camera3.enabled = false;
}
void Update()
{
if(isCamera1Active == 1){
camera1.enabled = true;
camera2.enabled = false;
camera3.enabled = false;
}
else if(isCamera1Active == 2){
camera1.enabled = false;
camera2.enabled = true;
camera3.enabled = false;
}
else if(isCamera1Active == 3){
camera1.enabled = false;
camera2.enabled = false;
camera3.enabled = true;
}
}
이제 상점으로 가는 스크립트를 참고해서 전투 장면으로 넘어가도록 만들어보자
public GPSManager player;
public CameraSwitch cameraswitch;
// 버튼을 눌렀을 때 호출되는 함수
public void GoTo()
{
player.ismove = false;
cameraswitch.isCamera1Active = 2;
}
이건 상점으로 가는 스크립트다
이걸 전투 장면 이동으로 이식하자
void ChangeScene()
{
player.ismove = false;
cameraswitch.isCamera1Active = 3;
}
이제 몬스터와 충돌하면 카메라를 이동시킨다
테스트 해보자
젠장 또 버그야
기존 전투 scence에서는 생성하는 방식으로 만들었는데, 메인에서 사용할려면 또 setactive를 사용해야 할 것 같다
일단 기존 월드의 몬스터는 충돌시 파괴되었는데, 파괴되지 않도록 해보자
if (other.CompareTag("Player") && canvasObject != null) // 충돌한 객체가 Player 태그를 가지고 있고 Canvas가 할당된 경우
{
GameObject moveScene = Instantiate(Move_scencePrefab, canvasObject.transform);
RectTransform rectTransform = moveScene.GetComponent<RectTransform>();
rectTransform.anchoredPosition = Vector2.zero; // Canvas의 중앙에 위치하도록 설정
if (monsterCollider != null)
{
monsterCollider.enabled = false;
}
}
이렇게 하면 플레이어와 충돌시 colider2d를 잃어버리면서 충돌을 꺼지고 남아만 있게 된다
.............................
............
......
..
if (monsterCollider != null)
{
GameObject moveScene = Instantiate(Move_scencePrefab, canvasObject.transform);
RectTransform rectTransform = moveScene.GetComponent<RectTransform>();
rectTransform.anchoredPosition = Vector2.zero; // Canvas의 중앙에 위치하도록 설정
monsterCollider.enabled = false;
move_scence.SetActive(true);
}
매커니즘을 수정해야 할 것 같다
기존은
몬스터와 충돌 -> 연출 오브젝트 생성, 연출 끝날시 씬 이동
의 과정을 거쳤는데, 이때 주체는 연출 오브젝트였다
이를 코루틴을 이용해서 연출이 끝나고 이동하는 방식으로 수정하자
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player") && canvasObject != null) // 충돌한 객체가 Player 태그를 가지고 있고 Canvas가 할당된 경우
{
if (monsterCollider != null)
{
GameObject moveScene = Instantiate(Move_scencePrefab, canvasObject.transform);
RectTransform rectTransform = moveScene.GetComponent<RectTransform>();
rectTransform.anchoredPosition = Vector2.zero; // Canvas의 중앙에 위치하도록 설정
monsterCollider.enabled = false;
move_scence.SetActive(true);
player.ismove = false;
wait();
cameraswitch.isCamera1Active = 3;
}
}
}
IEnumerator wait(){
yield return new WaitForSeconds(2f);
}
몬스터와 플레이어가 충돌했을때 함수를 수정했다
버그가 생겼다
몬스터와 충돌하면 무언가 꼬인다
스크립트를 아무리 뒤져봐도 안보인다
뭐지??
문제를 찾았다
public class Fight_reset : MonoBehaviour
{
/*
public GameObject World_UI;
public GameObject Shop_UI;
public GPSManager player;
// Update is called once per frame
void Update()
{
if(player.ismove == true){
World_UI.SetActive(true);
Shop_UI.SetActive(false);}
else{
World_UI.SetActive(false);
Shop_UI.SetActive(true);}
Gamemanager.Instance.iswin = false;
Gamemanager.Instance.fightend = false;
}
*/
}
이전에 만들어둔 싸움 종료 확인 오브젝트가 변수를 꼬아버리고 있었다
이제 정상적으로 작동할것이다
(급 추가 - 대화창을 json을 사용해서 구현할 수 있다. 언젠가는 수정?)
이제 몬스터와 전투씬을 다시 재구성 해야한다
public GameObject player;
public GameObject enemy;
public bool is_start = false;
// Update is called once per frame
void Update()
{
if(is_start == true && player == null && enemy == null){
player.SetActive(true);
enemy.SetActive(true);
}
}
몬스터와 플레이어가 충돌하면 몬스터와 플레이어를 true로 만드는 오브젝트를 하나 만든다
이 오브젝트가 앞으로 전투를 관리하게될 것 이다
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player")) // 충돌한 객체가 Player 태그
{
if (monsterCollider != null)
{
monsterCollider.enabled = false;
move_scence.SetActive(true);
player.ismove = false;
wait_to_start();
}
}
}
IEnumerator wait_to_start(){
yield return new WaitForSeconds(3f);
fight.is_start = true;
cameraswitch.isCamera1Active = 3;
}
몬스터는 플레이어와 충돌하면 전투 관리 오브젝트의 변수를 true로 만들고 카메라를 이동시켜 전투를 시작하게 한다
근데 왜 스폰 안됨????
원인을 찾아보자
if(is_start == true && player == null && enemy == null){
player.SetActive(true);
enemy.SetActive(true);
}
아마 이 null판정이 이상한 것 같다 빼보자
정상적으로 작동한다
이제 전투에 살을 붙여보자
그전에 UI가 꼬여서 왜그런지 봤더니, 이전글에서 전투 리셋 오브젝트에 UI를 관리하게 만들어놨다
아이고 골이야
지금이라도 매니저로 승격시켜 주자, 이거때문에 1시간을 스크립트를 뒤지고 있었다
void Update()
{
if(player.ismove == true && CameraSwitch.Instance.isCameraActive == 1){
World_UI.SetActive(true);
Shop_UI.SetActive(false);
Fight_UI.SetActive(false);
}
else if(player.ismove == false && CameraSwitch.Instance.isCameraActive == 2){
World_UI.SetActive(false);
Shop_UI.SetActive(true);
Fight_UI.SetActive(false);
}
else if(player.ismove == false && CameraSwitch.Instance.isCameraActive == 3){
World_UI.SetActive(false);
Shop_UI.SetActive(false);
Fight_UI.SetActive(true);
}
}
이제 UI매니저는 카메라 매니저의 값을 확인하며 UI를 바꾼다.......????
이거 그냥 카메라 매니저에 쑤셔넣는게 이득 아닌가?
일단은 그냥 사용하겠다
.........................
..............
......
...
.
싱글톤을 남발하다 매니저가 죄다 꼬였다
매니저를 남발하지 말자
전투씬을 구현했다
이제 전투가 끝났을때 어떻게 될지 만들어야 한다
void Update()
{
if(Gamemanager.Instance.player_HP > 0)
rb.velocity = new Vector2(speed, rb.velocity.y);
else if(Gamemanager.Instance.player_HP <= 0){
Gamemanager.Instance.iswin = false;
rb.AddForce((transform.up * backwardForce)/2);
rb.velocity = new Vector2(-speed*30, rb.velocity.y);
delay();
}
if(Gamemanager.Instance.fightend == true){
gameObject.transform.position = new Vector3(-9,-50,0);
gameObject.SetActive(false);
}
}
플레이어 오브젝트, 몬스터 오브젝트는 게임 매니저의 fightend가 true가 되면 원래 자리를 찾아간다
if(Gamemanager.Instance.fightend == true){
gameObject.transform.position = new Vector3(9,-50,0);
HP = 30;
gameObject.SetActive(false);
}
몬스터는 추가적으로 체력을 회복한다
public enemy_fight enemy;
public GameObject out_btn_fight;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Gamemanager.Instance.player_HP <= 0 || enemy.HP <= 0)
{
StartCoroutine(EndFightAfterDelay(3.0f));
}
}
IEnumerator EndFightAfterDelay(float delay)
{
if (Gamemanager.Instance.fightend) yield break;
yield return new WaitForSeconds(delay);
out_btn_fight.SetActive(true);
}
이제 플레이어, 혹은 몬스터의 HP가 0 이하일시 3초뒤 나가는 버튼을 생성한다
public GPSManager player;
public CameraSwitch C;
// 버튼을 눌렀을 때 호출되는 함수
public void GoToWorldcamera()
{
player.ismove = true;
C.isCameraActive = 1;
Gamemanager.Instance.fightend = true;
}
나가는 버튼을 누르면 전투씬을 초기화 하고, 월드로 돌아간다
근데 fightend가 초기화가 안된다??
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class fight_start_spwan : MonoBehaviour
{
public GameObject player;
public GameObject enemy;
public enemy_fight e;
public bool is_start = false;
// Update is called once per frame
void Update()
{
if(is_start == true){
player.SetActive(true);
enemy.SetActive(true);
}
else{
player.transform.position = new Vector3(-9f, -50f, 0f);
enemy.transform.position = new Vector3(9f,-50f, 0f);
e.HP = 30;
player.SetActive(false);
enemy.SetActive(false);
}
}
}
게임 매니저 변수가 아니라 따로 관리해 보자
그래도 안된다
뭐지??
전 바보입니다
버튼에 스크립트 연결도 안하고 뭘 바란거지?
근데 전투에서 나가는 버튼이 남아있는 버그가 보인다
이건 그냥 하드 코딩으로 해결하자
if (Gamemanager.Instance.player_HP <= 0)
{
lose.SetActive(true);
out_btn_fight.SetActive(true);
}
else if(e.HP <= 0){
win.SetActive(true);
out_btn_fight.SetActive(true);
}
else
{
win.SetActive(false);
lose.SetActive(false);
out_btn_fight.SetActive(false);
}
테스트의 시간이다
역시 하드코딩이야! 모든걸 해결해줘!
너무 길어져서 다음글로...