유니티
로그라이크 - MovingObject.cs
hololol
2019. 6. 24. 14:51
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//movingObject=>상속할 부모 역할이다. (추상클래스)
//player, enemy는 움직이는게 똑같다.(현재 위치 =>목적지 위치로 이동하는게 똑같음)
//겹치는 부분, 공통 부분을 상속을 받게끔 구성한다.
public abstract class MovingObject : MonoBehaviour
{
public float moveTime=0.1f;
public LayerMask blockingLayer; //상호작용을 위해서 LayerMask를 설정한다.
//player과 wall은 상호작용. player<==>wall, enemy<=>player
float inverseMoveTime;
BoxCollider2D boxCollider;
Rigidbody2D rb2D;
//오버라이드 할 수 있게 가상메소드로 만든다
protected virtual void Start()
{
boxCollider = GetComponent<BoxCollider2D>();//박스 콜라이더를 잠깐 끄기위해 getComponent로 가져온다.
rb2D = GetComponent<Rigidbody2D>();//목적지
inverseMoveTime = 1 / moveTime;
}
//부드럽게 이동하기 (while)
protected IEnumerator SmoothMovement(Vector3 end)
{
//목적지에 도착했는지 알아내기(남아있는 거리를 잰다)
float distance = (transform.position - end).sqrMagnitude; //sqrMagnitude는 (거리의)제곱. 제곱을 하면 플러스가 됨.
while(distance > float.Epsilon)
{
//MoveTowards = 직선으로 3번째 값만큼 이동한다
//rb2D.position = 나의위치
//end = 목적지
//inverseMoveTime * Time.deltaTime = 1/60만큼 끊어서 간다
Vector3 newPos = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime * Time.deltaTime);
//나의 위치로 진짜로 움직여라
rb2D.MovePosition(newPos);
//한번 움직이고 남은거리 계산
distance = (transform.position - end).sqrMagnitude;
//한 프레임만큼 휴식한다.
yield return null;
}
}
//앞에 장애물이 있는가 없는가
//반환형이 여러개이고 싶을때 out을 씀.
protected bool Move(int xDir, int yDir, out RaycastHit2D hit)
{
Vector2 start = transform.position; //start = 나의 위치
Vector2 end = start + new Vector2(xDir, yDir); //end = start에서 움직여야하는 나의위치
//나도 레이저에 걸리니 boxCollider 끔
boxCollider.enabled = false;
//start에서 end로 한 줄로 레이저를 쏘시오. blockingLayer가 아닌것은 인식하지 않음
hit = Physics2D.Linecast(start, end, blockingLayer);
//다시 Collider 살리기
boxCollider.enabled = true;
//부딪힌것이 없으면 나의 목적지로 움직인다
if (hit.transform == null)
{
StartCoroutine(SmoothMovement(end));
return true; //움직였다고 리턴 true값 반환
}
return false; //부딪히면 false 리턴
}
//공격하면서 움직인다
//하나의 메소드를 만들었는데 반응하는 대상이 다르다
protected virtual void AttempMove<T>(int xDir, int yDir)
where T:Component //T자리에는 Component 대상만 들어갈 수 있다
{
RaycastHit2D hit;
bool canMove = Move(xDir, yDir, out hit);
if (hit.transform == null) return;
//자료형에 컴포넌트를 가져와서 담는다
T hitComponent = hit.transform.GetComponent<T>();
//움직이지않고 hitComponent가 null이 아니라면
if (!canMove && hitComponent != null)
OnCantMove(hitComponent);
}
//본문이 존재하지 않는 추상메소드 생성
protected abstract void OnCantMove<T>(T component)
where T : Component;
}