
플레이어코드는 는 기능별로 세개의 스크립트로 나누었다.

private void Start() {
rigid = GetComponent<Rigidbody2D>();
thisCol = GetComponent<Collider2D>();
sprender = GetComponent<SpriteRenderer>();
pSprender = Psprite.GetComponent<SpriteRenderer>();
face = 1;
FirstSend();
curMP = maxMP;
}
private void Update() {
FaceDir();
GetComponent<Weapon_Attack>().Attack();
GetComponent<Weapon_Attack>().AttackTime();
Dash();
DetectSlope();
GetComponent<Weapon_Attack>().DetectCharging();
GroundCheck1();
OnOffDetectGround();
FlipSP();
SendGM();
//BodySense();
}
private void FixedUpdate() {
Move();
Jump();
}
플레이어의 생명주기
//움직임/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Move(){
//////////////////////////////////////////////////////////////////////////////////////////////////////////////움직임 제어 조건
if(isDash == true){ // 대쉬상태일 경우
inputX = dashDir; // 대쉬를 할 방향으로 고정
}
else if(isCharginAtk || isCharging){ //차징샷을 충전중이거나 공격을 실행중일 시
inputX = 0; //좌우 입력을 무시한다.
}
else{ // 대쉬상태가 아닐 경우
inputX = Input.GetAxisRaw("Horizontal"); //수평계 입력을 방향으로 설정
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////슬로프 조건
if(isSlope && isGround1 && !isJump){
rigid.velocity = perp * moveSpeed * inputX * -1;
//transform.Translate(perp * moveSpeed * inputX);
}else if(!isSlope && isGround1){
//rigid.velocity = new Vector2(inputX * moveSpeed, 0);
//transform.Translate(new Vector2(inputX * moveSpeed,0));
}else if(!isGround1){
rigid.velocity = new Vector2(inputX * moveSpeed, rigid.velocity.y);
}
if(isJump){
rigid.velocity = new Vector2(inputX * moveSpeed / 1.5f, rigid.velocity.y);
//transform.Translate(Vector2.right * inputX * moveSpeed * 0.5f);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////움직임 연산
rigid.velocity = new Vector2(inputX * moveSpeed, rigid.velocity.y);
//transform.Translate(Vector2.right * inputX * moveSpeed * Time.deltaTime);
}
플레이어 개체의 이동은 오브젝트에 속력을 더해 움직이도록 구현했다. 이동은 수평계만 입력받았으며 점프는 따로 기능을 분리하였다.
이 때 각 상황에 맞게 bool 값을 참고하여 움직임에 제한을 두었다.
void DetectSlope(){ //경사로 감지 및 경사로상의 움직임
if(isSlope && inputX == 0){//x축 입력이 없을 때
rigid.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezeRotation; //x축의 이동과 회전을 잠금
}else{ //이외의 경우
rigid.constraints = RigidbodyConstraints2D.FreezeRotation; //회전만 잠금(x축의 이동잠금은 해제)
}
RaycastHit2D rayHit = Physics2D.Raycast(checkPos.position, Vector2.down, distance, LayerMask.GetMask("groundMask")); //checkPos의 위치로부터 아래방향으로 distance의 거리만큼 groundMask만 스캔
Debug.DrawRay(checkPos.position, Vector2.down * distance, Color.green);//위에서 그려진 ray를 가시화. 색은 Green.
if(rayHit){
angle = Vector2.Angle(rayHit.normal, Vector2.up); //rayHit.normal : 스캔된 오브젝트의 표면에서 수직방향을 반환, Angle : 두 지점의 각도를 구함
Debug.DrawLine(rayHit.point, rayHit.point + rayHit.normal, Color.red); //Ray가 닿은 부분부터 닿은 부분으 수직으로 선을 그린다. 색은 Red.
perp = Vector2.Perpendicular(rayHit.normal).normalized; //위에서 그려진 법선을 90도 회전한 각도를 저장한다.
Debug.DrawLine(rayHit.point, rayHit.point + perp, Color.blue); //Ray가 닿은 부분부터 닿은부분의 수직 법선을 90도 회전한 값으로 그린다. 색은 blue.
//Debug.Log(perp);
if(angle != 0){
isSlope = true;
}else{
isSlope = false;
}
}
}
void GroundCheck1(){ //지면 감지
if(rigid.velocity.y > 0.1f && !isSlope){
isGroundBox = Physics2D.BoxCast(Vector2.zero,Vector2.zero,0,Vector2.zero);
}else{
//isGround = Physics2D.OverlapCircle(checkPos.position, checkRadius, LayerMask.GetMask("groundMask"));
int layerMask = (1 << LayerMask.NameToLayer("Player")); //플레이어 레이어 제외
layerMask = ~layerMask ;
isGroundBox = Physics2D.BoxCast(groundCheckBox1.transform.position, groundCheckBox1.transform.localScale, 0, Vector2.down, 0, layerMask);
}
if(isGroundBox && isGroundBox.collider.tag == "Land"){
isGround1 = true;
}else{
isGround1 = false;
}
}
경사로를 탐지하고 경사로를 오를 때, 내려올 때 중력의 영향에 의해 속도가 변하는것을 막고, 경사로 상에서 아무런 입력이 없을 때 오브젝트가 중력에 이끌려 조금씩 미끄러지는 현상을 완화하기 위한 기능을 구현했다.
2D 경사로 미끄러짐 (구현방법)

1.플레이어 아래 세로로 그어진 초록색 Ray에 지면이 감지된다.
2.이 지면의 각도에 수직한 빨간색 선을 그린다.
3.지면의 각도는 이 빨간선을 다시 90도 회전한 것(파란색 선)과 동일함으로 그 각도를 저장한다.
4.경사면이 아니라고 판단 될 시 발 아래 파란색 사각형을 그려 땅위임을 판단한다.
private void Jump()
{
if (isGround1 == true){
if (Input.GetAxis("Jump") != 0 && !(isCharginAtk || isCharging)) //공격을 차징중이거나 차징공격을 실행중일 때는 점프를 할 수 없다.
{
isJump = true;
//rigid.velocity = new Vector2(rigid.velocity.x, 0);
rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
}
}
if(isGround1 && rigid.velocity.y <= 0){
isJump = false;
}
}
private void Dash(){
if((inputX != 0)&&(Input.GetKeyDown(KeyCode.LeftShift))){
Debug.Log("DashKey Down");
dashDir = Input.GetAxisRaw("Horizontal"); //누르고 있는 방향을 대쉬 방향으로 고정
isDash = true; //대쉬 상태 on
moveSpeed = moveSpeed * dashPower; //이동속도를 증가
Invoke("EndDash", 0.1f); //0.1초 후 감속 함수를 실행
}
}
private void EndDash(){
moveSpeed = moveSpeed / dashPower; //증가했던 속도만큼 다시 감소
isDash = false; //대쉬 상태 off
}
플레이어의 점프와 대쉬 기능