오늘 할일
오전
카메라 따라가기, 화면 밖으로 나가는거 막기 - 완료
버섯 생성 후 옆으로 이동 - 완료
버섯 먹으면 크기 증가 - 완료
적 움직이기 구현, 부딪히면 gameover scene 으로 이동
증가한 상태에서 부딪히면 크기 감소,- 진행 중
기본크기 상태에서 부딪히면 게임오버 - 진행 중
위에서 밟으면 적이 사라짐(죽음)
코인 애니메이션
오후
-map 1에서 크기가 작으면 map2, map 3에서도 크기가 작아야하고, 크면 커야됨
빈오브젝트 생성해서 마리오 생성위치 잡고 prefab으로 동적으로 생성해야함
-SUCCESS UI에 저장된 점수 표시하기
-성에 도착하면 시간 0, 점수 비례해서
-증가완료 후 SUCCESS UI로 이동
-ui 유지하기
-포탈에서 느려지기
집가서 할 거
map1-> map2 는 해주셨으니까 map2-> map3 하기
1. 카메라 따라다니기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cameraController : MonoBehaviour
{
Vector3 cameraPosition = new Vector3(0, 0, -10);
[SerializeField]
private GameObject Player;
void Start()
{
}
private void FixedUpdate()
{
transform.position = Player.transform.position + cameraPosition;
}
}
카메라는 잘 따라다니지만 위치 조정 및 옆 부분을 막을 필요가 있음
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cameraController : MonoBehaviour
{
[SerializeField]
Transform playerTransform;
[SerializeField]
Vector3 cameraPosition;
[SerializeField]
Vector2 center;
[SerializeField]
Vector2 mapSize;
[SerializeField]
float cameraMoveSpeed;
float height;
float width;
void Start()
{
playerTransform = GameObject.Find("mario").GetComponent<Transform>();
height = Camera.main.orthographicSize;
width = height * Screen.width / Screen.height;
}
void FixedUpdate()
{
LimitCameraArea();
}
void LimitCameraArea()
{
transform.position = Vector3.Lerp(transform.position,
playerTransform.position + cameraPosition,
Time.deltaTime * cameraMoveSpeed);
float lx = mapSize.x - width;
float clampX = Mathf.Clamp(transform.position.x, -lx + center.x, lx + center.x);
float ly = mapSize.y - height;
float clampY = Mathf.Clamp(transform.position.y, -ly + center.y, ly + center.y);
transform.position = new Vector3(clampX, clampY, -10f);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireCube(center, mapSize * 2);
}
}
맵 사이즈에 맞게 조절
2. 마리오 밖으로 나가는거 막기
이렇게 하면 맵마다 크기가 달라서 제대로 막을수가 없음
map 2는 막을 필요가 없어서 그냥 map1과 map3의 크기를 똑같이 맞추고 화면을 막는것이 좋을거같음
if (dirX != 0)//달리고 있다면?
{
//if (!this.isJump)//좌우를 쳐다보는데 점프 상태가 아니라면 => 걷는중
//{
this.anim.SetInteger("State", 1);
this.anim.SetBool("isJump", false);
//}
this.transform.localScale = new Vector3(dirX *Mathf.Abs(this.transform.localScale.x), this.transform.localScale.y, 1);
this.transform.position = new Vector3(Mathf.Clamp(this.transform.position.x, -8.1f, 25.9f),this.transform.position.y, 0);
}
3. 버섯 먹으면 크기 커짐
private void OnCollisionStay2D(Collision2D collision)
{
if (collision.gameObject.tag == "portal" && Input.GetKey(KeyCode.DownArrow))
{
this.uiDirector.SaveData();
SceneManager.LoadScene("Map2Scene");
}
else if (collision.gameObject.tag == "mushroom")
{
this.gameObject.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
Destroy(collision.gameObject);
}
}
문제점1.
this.transform.localScale = new Vector3(dirX *0.5f, 0.5f, 1); //달리는 방향 쳐다보기
이 부분 때문에 크기가 커졌다가 오른쪽이나 왼쪽 키보드 누르면 다시 0.5로 크기가 돌아옴
=> this.transform.localScale = new Vector3(dirX *this.transform.localScale.x, this.transform.localScale.y, 1);
현재 크기로 바꿔줌
문제점2. 크기는 커지지만 현재 x의 값이 음수 양수 계속 왔다갔다 하면서 이상한 움직임을 보임
=> this.transform.localScale = new Vector3(dirX *Mathf.Abs(this.transform.localScale.x), this.transform.localScale.y, 1);
절댓값을 해줌
4. 버섯 생성되고-> 오른쪽으로 이동 -> 굴뚝에 부딪히면 방향 바껴서 왼쪽으로 이동 후 옆으로 떨어지면 사라지기
mushroomController 생성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MushroomController : MonoBehaviour
{
public float moveSpeed = 0.05f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
this.transform.Translate(this.moveSpeed, 0, 0);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "portal")
{
this.transform.Translate(-this.moveSpeed, 0, 0);
}
}
}
아래로 떨어지지 않음 => 중력 적용 => mushroomPrefab에 rigidbody 컴포넌트 추가
문제점 .굴뚝 만났을 때 방향 바뀌지 않음
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MushroomController : MonoBehaviour
{
public float moveSpeed = 0.05f;
// Update is called once per frame
void Update()
{
this.transform.Translate(this.moveSpeed, 0, 0);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "portal")
{
moveSpeed = moveSpeed * -1;
}
}
}
수정
떨어지면 사라지기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MushroomController : MonoBehaviour
{
public float moveSpeed = 0.05f;
// Update is called once per frame
void Update()
{
this.transform.Translate(this.moveSpeed, 0, 0);
if (this.transform.position.y < -3.5f)
{
Destroy(this.gameObject);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "portal")
{
moveSpeed = moveSpeed * -1;
}
}
}
+ freeze rotation 체크
5. 적 움직임 구현 및 애니메이션
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MushroomController : MonoBehaviour
{
public float moveSpeed = 0.05f;
// Update is called once per frame
void Update()
{
this.transform.Translate(this.moveSpeed, 0, 0);
if (this.transform.position.y < -3.5f)
{
Destroy(this.gameObject);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "portal")
{
moveSpeed = moveSpeed * -1;
}
if (collision.gameObject.tag == "portal2")
{
moveSpeed = moveSpeed * -1;
}
}
}
부딪히면 게임오버씬으로 이동
private void OnCollisionStay2D(Collision2D collision)
{
if (collision.gameObject.tag == "portal" && Input.GetKey(KeyCode.DownArrow))
{
this.uiDirector.SaveData();
SceneManager.LoadScene("Map2Scene");
}
else if (collision.gameObject.tag == "mushroom")
{
this.gameObject.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
Destroy(collision.gameObject);
}
else if (collision.gameObject.tag == "portal2" && Input.GetKey(KeyCode.RightArrow))
{
SceneManager.LoadScene("Map3Scene");
}
else if (collision.gameObject.tag == "enemy")
{
SceneManager.LoadScene("GameOverScene");
}
}
marioController스크립트에 추가
6. 커졌을때 부딪히면 크기 감소 , 작았을때 부딪히면 게임오버
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "enemy")
{
if (this.transform.localScale.x == 0.5f)
{
SceneManager.LoadScene("GameOverScene");
}
else if (this.transform.localScale.x == 0.6f)
{
this.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
}
}
}
문제점 . 작아지고 바로 게임오버씬으로 이동해버린다. 부딪히고 일정 시간 동안은 호출하지 않아야한다., 코루틴으로 하려다가 함수가 collisionEnter라서 하기 어려움 그냥 bool을 이용해서 한번만 되도록 함
private bool isSmall = false;
private void OnCollisionEnter2D(Collision2D collision)
{
if (isSmall == false)
{
if (collision.gameObject.tag == "enemy")
{
if (this.transform.localScale.x == 0.5f)
{
SceneManager.LoadScene("GameOverScene");
}
else if (this.transform.localScale.x == 0.6f)
{
this.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
this.isSmall = true;
}
}
}
}
문제점 2. 이러면 다른씬에서 적을 만났을때 실행되지 않음
6. 코인애니메이션
그냥 transform의 rotation의 y 값을 15초에 360도로 변경하여 애니메이션을 만들었다.
7. 마리오 프리팹으로 동적 생성하기( 크기 정보 그대로 가지고 원하는 위치에서 )
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
public class Map1Main : MonoBehaviour
{
[SerializeField]
private UIDirector uiDirector;
[SerializeField]
private GameObject uiPrefab;
private Transform parent;
[SerializeField]
private GameObject marioPrefab;
[SerializeField]
private Transform marioTrans;
[SerializeField]
private CameraController cameraController;
private MarioController marioController;
// Start is called before the first frame update
void Start()
{
GameObject uiGo = Instantiate(this.uiPrefab);
uiGo.transform.SetParent(parent, false);
GameObject marioGo = Instantiate(marioPrefab);
marioGo.transform.position = this.marioTrans.position;
marioGo.name = "Mario";//Mario 이름으로 생성됨
cameraController.Init();
this.marioController = marioGo.GetComponent<MarioController>();
this.marioController.onGetMushroom = (scale) => {
this.marioController.Bigger(scale);//크기 증가하는 함수
Debug.LogFormat("버섯획득 : isBig => {0}", this.marioController.IsBig);//true or false 출력
};
this.marioController.onChangeScene = (sceneName) => {
this.ChangeScene(sceneName);//레이 검사해서 포탈 있으면 onChangeScene 호출하고 있음
};
}
private void ChangeScene(string sceneName)
{
bool isBig = this.marioController.IsBig; //현재 씬에서 커진 상태 다음 씬담당 메인에게 전달
Debug.LogFormat("isBig: {0}", isBig);
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName);
//씬로드가 완료되면 호출 되는 이벤트에 대리자 연결
asyncOperation.completed += (obj) => {
switch (sceneName)
{
//굴둑 동전 먹으러
case "Map2Scene":
//다음 씬 메인 가져오기
Map2main map2Main = GameObject.FindObjectOfType<Map2main>();
map2Main.Init(isBig); //초기화 //마리오 생성
break;
}
};
}
public void EatCoin()
{
uiDirector.IncreaseScore(50);
uiDirector.IncreaseCoin();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
private Transform playerTransform;
[SerializeField]
Vector3 cameraPosition;
[SerializeField]
Vector2 center;
[SerializeField]
Vector2 mapSize;
[SerializeField]
float cameraMoveSpeed;
float height;
float width;
public void Init()//시작하자마자 말고, 호출될때 (마리오 생성되고) 호출되어야함
{
playerTransform = GameObject.Find("Mario").GetComponent<Transform>();//생성된 마리오 이름의 오브젝트의 위치를 찾아서 저장
height = Camera.main.orthographicSize;
width = height * Screen.width / Screen.height;
}
void FixedUpdate()
{
LimitCameraArea();
}
void LimitCameraArea()
{
//초기화 되기전에는 호출되면 안됨
if (playerTransform == null) return;
transform.position = Vector3.Lerp(transform.position,
playerTransform.position + cameraPosition,
Time.deltaTime * cameraMoveSpeed);
float lx = mapSize.x - width;
float clampX = Mathf.Clamp(transform.position.x, -lx + center.x, lx + center.x);
float ly = mapSize.y - height;
float clampY = Mathf.Clamp(transform.position.y, -ly + center.y, ly + center.y);
transform.position = new Vector3(clampX, clampY, -10f);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireCube(center, mapSize * 2);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.VisualScripting;
using Unity.VisualScripting.Antlr3.Runtime.Tree;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MarioController : MonoBehaviour
{
private Rigidbody2D rBody2D;
private float jumpForce = 500f;
private float moveForce = 60f;
private Animator anim;
private bool isJump = false;
private bool isLongJump = false;
//[SerializeField]
//private UIDirector uiDirector;
[SerializeField]
private Transform rayOrigin; //체크 아래쪽 하기 위한 레이 발사 시작 위치
//private float scaleChange = 0;
public System.Action<float> onGetMushroom; //대리자 변수 정의
public System.Action<string> onChangeScene;
// Start is called before the first frame update
void Start()
{
this.rBody2D = this.GetComponent<Rigidbody2D>();
this.anim = this.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
//jump
if (Input.GetKeyDown(KeyCode.Space))
{
// 이중점프 막기
if (this.rBody2D.velocity.y == 0)
{
this.rBody2D.AddForce(Vector2.up * this.jumpForce);
if (this.isJump == false)
{
this.isJump = true;
}
}
}
if (this.isJump)
{
if (this.rBody2D.velocity.y > 0)
{
// Jumping
this.anim.SetBool("isJump", true);
}
else if (this.rBody2D.velocity.y < 0)
{
// Falling
this.anim.SetBool("isJump", false);
}
}
//if (Input.GetButtonUp("Horizontal"))
//{
// this.rBody2D.velocity = new Vector2(this.rBody2D.velocity.normalized.x * 0.8f, this.rBody2D.velocity.y);
//}
//if (this.isJump)// space를 눌렀는데
//{
//if (this.rBody2D.velocity.y > 0)// 점프상태
//{
// this.anim.SetInteger("State", 2);
//}
//}
int dirX = 0;
if (Input.GetKey(KeyCode.LeftArrow))
{
dirX = -1;
}
if (Input.GetKey(KeyCode.RightArrow))
{
dirX = 1;
}
float speedX = Mathf.Abs(this.rBody2D.velocity.x);//절대값(속도는 음수 나오면 안됨), 가속도
if (speedX < 5f)//가속도 제한
{
this.rBody2D.AddForce(new Vector2(dirX, 0) * this.moveForce);
}
//움직이는 방향으로 쳐다보기
if (dirX != 0)//달리고 있다면?
{
//if (!this.isJump)//좌우를 쳐다보는데 점프 상태가 아니라면 => 걷는중
//{
this.anim.SetInteger("State", 1);
this.anim.SetBool("isJump", false);
//}
this.transform.localScale = new Vector3(dirX *Mathf.Abs(this.transform.localScale.x), this.transform.localScale.y, 1);
this.transform.position = new Vector3(Mathf.Clamp(this.transform.position.x, -8.1f, 25.9f),this.transform.position.y, 0);
}
else//좌우를 쳐다보지도 않고 점프 상태도 아니라면 =>idle
{
if (this.isJump==false)
{
this.anim.SetInteger("State", 0);
this.anim.SetBool("isJump", false);
}
}
this.anim.speed = speedX / 2.0f;
//길게 누르면 높은 점프 짧게 누르면 낮은 점프
if (Input.GetKey(KeyCode.Space))
{
isLongJump = true;
}
else if (Input.GetKeyUp(KeyCode.Space))
{
isLongJump = false;
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log("아래 들어갈때가 있는지 확인한다");
this.CheckPortalBelow();
}
}
private Coroutine routineCheckPortalBelow;
private void CheckPortalBelow()
{
if (this.routineCheckPortalBelow != null) StopCoroutine(this.routineCheckPortalBelow);
this.routineCheckPortalBelow = this.StartCoroutine(this.CoCheckPortalBelow());
}
private IEnumerator CoCheckPortalBelow()
{
yield return null;
//레이를 만듬
Ray ray = new Ray(this.rayOrigin.transform.position, this.transform.up * -1);//this.transform.up*-1 = 아래로 레이만들기
Debug.DrawRay(ray.origin, ray.direction, Color.red, 10f);
LayerMask mask = 1 << LayerMask.NameToLayer("Mario");//마리오Layer만(6)
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction, 1, ~mask);//~mask= 마리오 빼고 다
if (hit)
{
Debug.Log(hit.collider.gameObject.name);
if (hit.collider.gameObject.name == "portal2")
{
this.onChangeScene("Map2Scene");
}
}
}
private void FixedUpdate()
{
if (isLongJump && this.rBody2D.velocity.y > 0)
{
this.rBody2D.gravityScale = 1.2f;
}
else
{
this.rBody2D.gravityScale = 2.5f;
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "coin")
{
Destroy(other.gameObject);
//this.main1.EatCoin();
//this.uiDirector.IncreaseScore(50);
//this.uiDirector.IncreaseCoin();
}
else if (other.gameObject.tag == "flag")
{
//this.uiDirector.IncreaseScore(400);
}
else if (other.gameObject.tag == "castle")
{
//this.uiDirector.time = 0;
//코루틴 하면 좋을거같음
//SceneManager.LoadScene("GameOverScene");
}
//this.uiDirector.UpdateUI();
}
private void OnCollisionStay2D(Collision2D collision)
{
}
private bool isSmall = false;
private void OnCollisionEnter2D(Collision2D collision)
{
//if (collision.gameObject.tag == "portal")
//{
// this.onChangeScene("Map2Scene");
//}
if (collision.gameObject.tag == "mushroom")
{
Destroy(collision.gameObject); //버섯 제거
this.onGetMushroom(0.6f); //대리자 호출
}
//else if (collision.gameObject.tag == "portal2" && Input.GetKey(KeyCode.RightArrow))
//{
// SceneManager.LoadScene("Map3Scene");
//}
if (isSmall == false)
{
if (collision.gameObject.tag == "enemy")
{
if (this.transform.localScale.x == 0.4f)
{
SceneManager.LoadScene("GameOverScene");
}
else if (this.transform.localScale.x == 0.6f)
{
this.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f);
this.isSmall = true;
}
}
}
}
public void Bigger(float scale)
{
if (this.IsBig)
{
Debug.Log("이미 커진 상태 입니다.");
}
else //작은 상태면 크기증가
{
this.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
this.IsBig = true;
}
}
public bool IsBig//true,false
{
get; set;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SocialPlatforms.Impl;
using UnityEngine.UI;
public class Map2main : MonoBehaviour
{
//[SerializeField]
//private Text txtScore;
//[SerializeField]
//private Text txtCoin;
//[SerializeField]
//private Text txtTime;
//[SerializeField]
//private Text txtMapName;
//private int score;
//private int coin;
//private float time;
[SerializeField]
private GameObject uiPrefab;
private Transform parent;
[SerializeField]
private GameObject marioPrefab;
[SerializeField]
private Transform marioTrans;
private MarioController marioController;
void Start()
{
//this.LoadData();
//this.txtMapName.text = string.Format("WORLD\n1-2");
//this.time = PlayerPrefs.GetFloat("Time");
////uiGo.transform.SetParent(parent, false);
///GameObject uiGo = Instantiate(this.uiPrefab);
}
public void Init(bool isBig)
{
//마리오 만들기
this.CreateMario(isBig);
//UI생성
GameObject uiGo = Instantiate(this.uiPrefab);
uiGo.transform.SetParent(parent, false);
}
// Update is called once per frame
//void Update()
//{
// this.time -= Time.deltaTime;
// this.txtTime.text = time.ToString("F0");
// this.txtTime.text = string.Format("TIME\n{0}", this.txtTime.text);
// this.SaveData();
//}
//public void LoadData()
//{
// int score = PlayerPrefs.GetInt("Score");
// this.txtScore.text = score.ToString();
// this.txtScore.text = string.Format("MARIO\n{0:D6}", score);
// this.txtCoin.text= PlayerPrefs.GetInt("Coin").ToString();
// this.txtCoin.text = string.Format("X {0}", this.txtCoin.text);
//}
//public void SaveData()
//{
// PlayerPrefs.SetInt("Score2", score);
// PlayerPrefs.SetFloat("Time2",time);
// PlayerPrefs.SetInt("Coin2", coin);
//}
private void CreateMario(bool isBig)
{
var go = Instantiate(marioPrefab);
go.transform.position = this.marioTrans.position;
this.marioController = go.GetComponent<MarioController>();
//이전씬에서 커진 상태 전달 받아 크게 만들기
if (isBig)
this.marioController.Bigger(0.6f);
}
}
크기 데이터를 저장하고 받아오려고 했는데 , 생각보다 단순하게 커진 상태면 -> 크기 크게 해서 생성 아니면 그냥 생성
포탈체크를 collider가 아닌 ray를 쏴서 확인
'2D 콘텐츠 제작 개발일지 (mario)' 카테고리의 다른 글
마리오 개발 8일차 (0) | 2023.09.20 |
---|---|
마리오 개발 7일차 (2) | 2023.09.19 |
마리오개발 5일차 (0) | 2023.09.17 |
마리오개발 4일차 (0) | 2023.09.16 |
마리오 개발 3일차(포탈이동/UI) (0) | 2023.09.15 |