
using UnityEngine;
public class StartPoint : MonoBehaviour
{
public string startPoint;//맵이 이동되면 플레이어와 맵 위치
private MovingObjcet thePlayer;
private CameraManager theCamera;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
theCamera = FindAnyObjectByType<CameraManager>();
thePlayer = FindAnyObjectByType<MovingObjcet>();
if(startPoint == thePlayer.currentMapName)
{
theCamera.transform.position = new Vector3(this.transform.position.x, this.transform.position.y, theCamera.transform.position.z);
thePlayer.transform.position = this.transform.position;
}
}
// Update is called once per frame
void Update()
{
}
}
sing System.Collections;
using UnityEngine;
public class MovingObjcet : MonoBehaviour
{
static public MovingObjcet instance;
public string currentMapName;//transferMap 스크립트에 있는 transferMapName변수의 값을 저장
private BoxCollider2D boxCollider;//박스콜라이더
public LayerMask layerMask;//통과불가 에이리어 설정
//케릭터 이동속도
public float speed;
//벡터(케릭터의 이동 방향)
private Vector3 vector;
//뛰기,평범하게 걷기
public float runSpeed;
private float applyRunSpeed;
private bool applyRunFlag = false;
//픽셀 단위로 움직이기 구현
public int walkCount;
private int currentWalkCount;
//한칸한칸 이동할때 플레그 형식으로 구현
private bool canMove = true;
private Animator animator;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
if(instance == null)
{
DontDestroyOnLoad(this.gameObject);
boxCollider = GetComponent<BoxCollider2D>();
animator = GetComponent<Animator>();
instance = this;
}
else
{
Destroy(this.gameObject);
}
}
//코루틴으로 이동제어 한칸 한칸 이동하게
IEnumerator MoveCoroutine()
{
while(Input.GetAxisRaw("Vertical") !=0 || Input.GetAxisRaw("Horizontal") != 0)
{
//시프트 키 입력 여부에 따라 뛰기 걷기 구분
if (Input.GetKey(KeyCode.LeftShift))
{
applyRunSpeed = runSpeed;
applyRunFlag = true;
}
else
{
applyRunSpeed = 0;
applyRunFlag = false;
}
//이동방향 벡터 움직임 구현
vector.Set(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"), transform.position.z);
//좌상,좌하 등 대각선 방향이동 장금
if(vector.x !=0)
vector.y = 0;
//에니메이터 불러오기
animator.SetFloat("DirX", vector.x);
animator.SetFloat("DirY", vector.y);
RaycastHit2D hit;//레이케스트
Vector2 start = transform.position; //캐릭터의 현제 위치 값
Vector2 end = start + new Vector2(vector.x * speed * walkCount, vector.y * speed * walkCount);
//캐릭터가 이동하고자하는 위치 값 그리고 사이즈
boxCollider.enabled = false;
hit = Physics2D.Linecast(start, end, layerMask);
boxCollider.enabled = true;
if (hit.transform != null)
break;
animator.SetBool("Walking", true);
//캐릭터 이동구현 코드
while (currentWalkCount < walkCount)
{
if (vector.x != 0)
{
//Translate는 현제 값에서 +를 해주는 코드
transform.Translate(vector.x * (speed + applyRunSpeed), 0, 0);
}
else if (vector.y != 0)
{
transform.Translate(0, vector.y * (speed + applyRunSpeed), 0);
}
if (applyRunFlag)
currentWalkCount++;//위의 applyRunFlas가 되면 추가되는 카운트 만약 아니라면 더해지지 않음
currentWalkCount++;//위의 카운트와는 별개의 카운트로 구분 됨
yield return new WaitForSeconds(0.01f);//0.01초마다 대기
}
currentWalkCount = 0;//0을 넣어서 반복문 초기화
}
animator.SetBool("Walking", false);
//한칸한칸 이동할때 bool값
canMove = true;
}
//매 프레임마다 이동명령을 받음
void Update()
{
if (canMove)
{
//이동 방향키 입력을 할때 쯔구르 처럼 상하좌우 구분하게 하는 코드
if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
{
//한칸 한칸 이동할때 bool값으로 canMove를 이용함
canMove = false;
StartCoroutine(MoveCoroutine());
}
}
}
}
using UnityEditor.U2D.Aseprite;
using UnityEngine;
using UnityEngine.SceneManagement;
public class TransferMap : MonoBehaviour
{
public string transferMapName;//이동할 맵의 이름
public Transform target;
public bool flag;
private CameraManager theCamera;
private MovingObjcet thePlayer;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
if(flag)
theCamera = FindAnyObjectByType<CameraManager>();
thePlayer = FindAnyObjectByType<MovingObjcet>();//다수객체에서 MovingObjcet를 찾아온다
}
// Update is called once per frame
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.name == "Player")
{
thePlayer.currentMapName = transferMapName;
if(flag)
SceneManager.LoadScene(transferMapName);
else
{
theCamera.transform.position = new Vector3(target.transform.position.x, target.transform.position.y, theCamera.transform.position.z);
thePlayer.transform.position = target.transform.position;
}
}
}
}
using UnityEngine;
public class CameraManager : MonoBehaviour
{
static CameraManager instance;
public GameObject target;//카메라가 따라갈 대상
public float moveSpeed;//카메라가 얼마나 빠른 속도로 대상을 추적할지
private Vector3 targetPosition;//대상의 현재 위치 값
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
if (instance != null)
{
Destroy(this.gameObject);
}
else
{
DontDestroyOnLoad(this.gameObject);
instance = this;
}
}
// Update is called once per frame
void Update()
{
if (target.gameObject != null)
{
targetPosition.Set(target.transform.position.x, target.transform.position.y, this.transform.position.z);
this.transform.position = Vector3.Lerp(this.transform.position, targetPosition, moveSpeed * Time.deltaTime);
//Time.deltaTime 초당 이동구현용 코드
}
}
}


이번 강좌에서는 씬 두개에 각각 맵을 만들어 둡니다

이동에 필요한 객체로 TranferPoint로 만들어 놓고 스크립트와 BoxCollider2D를 넣어 is Trgger도 세팅해 놓자
이 객체에 닿으면 캐릭터가 이동 한다
TransformMap 스크립트를 작성하자(위 작성된 스크립트 참조)

여기서 알아야 될 점은 위의 OnTriggerEnter2는 Collider에서 isTrgger이 체크되어 있으면 실행되는 함수다
우리는 실행을 위해 인스팩터에서 체크해둔다
collision.gameObject.name =="Player"
은 접촉한 대상이 "Player" 이라는 이름을 가지고 있다면을 의미한다
SceneManager.LoadScene는 다른 씬을 로드하는 명령어다

public로 이렇게 입력을 해 두면 문자열로 씬의 이름을 받아온다

이동할 씬의 이름은 SchoolFront이다
스크립트를 작성하고 게임을 만들때 주의 할 점은
RigidBody는 객체에 물리적인 신체를 부여하는 컴포넌트이고
BoxCollider와의 충돌을 감지하려면 이 컴포넌트가 꼭 필요하다
그리고 Rigidbody는 중력에 영향을 받기 때문에

빨간 글씨로 적은 1 Gravity Scale를 0으로 바꿔주고
Z축으로의 이동을 방지하기 위해 Freeze Rotation Z를 체크해 준다
그리고 씬 이동을 추가하기 위해서는

이 처럼 빌드한 씬을 드래그해서 넣어줘야 한다
그럼 씬을 이동할 수 있게 되는데 위치는 전에 있던 씬의 Vector3와 같은 곳에 오게 된다
그리고 중요한게 이렇게만 하면 캐릭터가 파괴되고 없어진다

그래서 이렇게 void start에 DontDestroyOnLoad(this.gameObject)를 입력하여 다른 씬으로 넘어가도 파괴되지 않도록 한다
카메라도 파괴되면 안되기 때문에 작성해준다
이제 원하는 씬의 자리로 이동하는 법을 알아보자!

여기서 StartPoint 스크립트를 작성해준다

이 스크립트는 우리가 이동할 곳을 지정해주는 스크립트다
이름이 같은 곳으로 이동해준다

위 스크립트는 스타트 포인트와 문장이 같다면 그 방향으로 이동해주는 스크립트다
카메라.transform.position = new Vector3(this.transform.positioon.x, this.transform.positioon.x, 카메라.transform.position
카메라 오브젝트를 포지션을 위치하고 = 새 포지션3(이 오브젝트의 위치.x ,이 오브젝트의 위치.y , 카메라 자신의 위치.z
플레이어 캐릭터의 경에는 그냥 자신의 포지션으로 오게 this로 바로 써놨다
여기까지 작성해서 끝나면 좋겠지만 우리는 맵의 이름을 받아 올 수 없는 스크립트를 짜놨다
대신 플레이어에 기록을 하고 불러올 수 있게 짤 수는 있다

무빙오브젝트 스크립트에 이걸 작성해 준다

StartPoint 함수에 플레이어의 정보를 받아올 수 있게 이 코드를 적어준다
생성만 했으므로 void start()에

작성해서 장착해준다
동영상 강좌에는 FindObjectOfType<>()를 사용하면 이제는 사용하지 않는다고 경고를 하는데
대체제로 FindAnyObjectByType가 사용된다
경고가 보기 싫으면 이렇게 필자처럼 작성해두자
이제 void OnTriggerEnter2D(Collider2D collision)
{
if(Collision.gameObject.name == "Player")
{의 안에

를 작성해 준다
그럼 MovingObject에 currentMapName에 값이 들어간다

그럼다음 이렇게 장착해준다

마지막으로 포인트 스타트에 작성해준다
여기까지 작성해주면 캐릭터까지 같이 이동하는게 보일 것이다
그런데 여기까지하면 카메라는 따라오는 문제가 생기는데
스타트 포인트에

를 작성해주고

void start()에 장착해준다

마지막으로 카메라의 위치도 잡아준다
캐릭터와 순간이동 되면서 따라오는 연출이 시작되늰게 아니라 바로 같이 오는 연출이 된다
여기까지는 좋은데 이 방법대로 이동을 하게되면 씬을 이동할때마다 캐릭터가 중복되서 나오는 문제가 생긴다

이런 식으로... 씬을 왔다 갔다 할 수록 더 많이 생긴다
이걸 방지하기 위해 인스턴스를 사용해 줄 거다

MovingObject에 위 변수를 만들어준다

그리고 void Start()에도 이렇게 작성해준다
인스턴스는 한 씬에 중복이 안생기게 해주는 것인데 이렇게 static로 공유되게 해주고 위 함수는
if는 인스턴스가 없다면 instance = this로 기존 캐릭터를 존재하게 해주는 것이고
else는 만약 중복되는 캐릭터가 존재하면 공유되는 캐릭터가 있으니 파괴해준다
는 뜻이다
카메라도 마찬가지 방법으로 인스턴스를 생성해준다(카메라 코드는 위에 다 작성되어서 생략함)
마지막으로 같은 씬에서 맵과 맵을 이동하는 방법을 설명한다


TransformMap스크립트에 이렇게 target를 작성해주자
트랜스프롬 맵을 이렇게 작성해주면 flag를 On/Off하여 맵과 씬 이동을 자유롭게 수정이 가능하다


오늘 강좌는 여기까지...
하루 두개 빡샘
'쯔꾸르식 유니티 게임 공부' 카테고리의 다른 글
7개량.카메라 영역 제한하기 개량(OnTrigger인식) (0) | 2025.01.02 |
---|---|
07.카메라를 영역을 맵 화면으로 제한하기 (0) | 2025.01.01 |
05.2D맵제작하기 (0) | 2024.12.31 |
04.카메라 플레이어 추적 (0) | 2024.12.30 |
03.이동불가 에이리어 만들기(레이캐스트 히트) (0) | 2024.12.29 |