공부/Unity

[Unity] 커비 개발 4일차 raycast로 벽 확인, 맵 워프, 경사면 미끄러짐, 적의 자동 점프

굴러다니다니 2023. 4. 14. 18:04
728x90

animation tag: copy, split, attack

 

1. raycast로 몬스터의 바로 앞에 벽이 있으면 방향을 바꾸게 설정

노란색만큼 raycast를 달고, ground와 부딪히면 방향 바꾸게 코드를 바꿔줬다.

좌우 raycast가 다르게 나온다.

 

2. 커비가 어떤 이유로든 대미지를 받으면 별을 뱉게했다 + 아무 능력 없어도 별 만드는 오류 잡기

완료!

 

3. 커비가 변신중일때는 능력을 벗지 못하게

조건을 추가해줬다.

 

4. 공중에 있을때 능력 변신 불가능

공중에서 변신하는 커비,,,, 에휴

변신 조건문에 점프중이 아닐때를 추가해서 오류 해결

 

5. 스테이지를 이동하는 문 스크립트

5 - 1 문 이미지를 아직 못구해서 그냥 네모 검정으로 만들고, script를 작성해준다.

public class makeWarp : MonoBehaviour
{
    [SerializeField] private Vector3 destination;
    [SerializeField] private Vector2 newMin;
    [SerializeField] private Vector2 newMax;
    [SerializeField] private int stage;
    private GameObject kirby;
    private Transform kirbyTransform;
    private GameObject[] enemies;

    private void Start()
    {
        enemies = kirby.GetComponent<KirbyControl>().enemies;
    }
    private void Awake()
    {
        kirby = GameObject.Find("Kirby");
    }

    public void doWarp()
    {
        for (int i = 0; i < enemies.Length; i++)
        {
            if (enemies[i].GetComponent<EnemyControl>().stage == stage) //해당 스테이지의 적들만 키기
            {
                enemies[i].SetActive(true);
            }
            else { enemies[i].SetActive(false);  }
        }
        kirbyTransform = kirby.GetComponent<Transform>();
        kirbyTransform.position = destination;
        Camera.main.GetComponent<MainCameraController>().minCameraBoundary = newMin;
        Camera.main.GetComponent<MainCameraController>().maxCameraBoundary = newMax;
    }

}

5 - 2 문에 콜라이더를 넣어주고, isTrigger체크를 한 다음, 커비가 문이랑 ontrigger 상태일때 커비가 위에 키를 누르면 문에서 지정해둔 destination 포지션으로 커비를 이동시킨다.

destination은 serializefield 처리해서 밖에서 입력

 

5 - 3 문 스크립트에서 이동할 시 카메라의 포지션도 바꿔주어야 함으로 이를 입력받아 설정이 가능하게 했다.

문 앞에서 위의 방향키를 누르면

카메라의 위치와 커비의 위치가 바뀐다

 

6. 현재 커비가 있는 스테이지가 아닌 적들은 setactive false로 안보이게 해준다.

스테이지 이동을 구현하고, 적들도 만들어두니 첫 스테이지에 커비가 있는데 두번째, 세번째 스테이지의 적들이 움직이고 있었다 -> 쓸데없이 동작하고 있기때문에 이를 setactive false로 지정해 적을 안보이게 해주었다.

-> enemyControl script에 현재 적이 있는 stage를 지정해주었으며, 문의 script에서 이를 비교해 해당 스테이지가 아닌 적들은 모두 안보이게 처리를 해줬다.

다만 첫 스테이지는 시작하자마자 보여야하기에 커비가 생성될 때 커비쪽에서 이를 제어해주었다.

있었던 웨이들두가 

커비가 문을 타고 나가자 없어진 모습 짜자잔

 

7. 경사면 미끄러짐 해결

커비 이동 키를 누르지 않아도 알아서 경사면은 빙판길을 만난거 마냥 주룩 미끄러진다.

Physics Material 2D를 생성해 마찰력을 2로 해주고, ground collider의 material에다가 집어넣어줬다

완만한 경사면은 안미끄러지지만, 경사면이 더 심해지면 조금 미끄러진다... 하지만 만족스러우니 괜춘

 

8. WaddleDee는 멍청하다!

우리의 웨이들디 친구는 제가 오던말던 계속 걸어가고 공격하지 않는다. (몸빵이 최선)

그래서 기존에 지정해둔 공격범위를 0, 0 으로 바꾸고 혹시 모를 사태에 대비해 Player layer를 찾는 기능을 nothing으로 바꿔 멍청하게 만들어 원작 고증 구현 완료!

 

9. 기본 적들도 종류가 두개! -> 점프가 가능하게 해보자

공격은 기본으로 있고, 다리로 걸어다니는 친구들과 점프로 돌아다니는 친구들이 존재한다.

이를 구별하기 위해 걸어다니는 애들은 type = 0, 뛰어다니는 애들은 type = 1로 설정해 스크립트를 추가로 수정해준다,

type이 1인애들은 애니메이션 창에서 jump trigger를 추가해서 점프로 이동하게 만들어준다 ! 완료!

점프로 탈출하시는 몬스터님

 

10. 변신한 능력의 아이콘과 글씨 띄우기

커비의 능력에 따라 update문으로 확인해 이를 바꿔준다.

Ui에서 빈 오브젝트 두개를 만들어 하나에 글씨 이미지들을, 하나에 아이콘 이미지들을 넣어놨다.

이것을 어떻게 스크립트로 접근하지,,? 해결!

위와 같이 gameobject 두 개를 선언해, 드래그로 empty object를 넣어준다.

gameobject.transform에서 find로 게임오브젝트 (이미지)를 찾을 수 있고, 이미지의 set active는 gameobject에서 바꾸는거라 <image>가 아니라 gameobject를 찾아서 false / true 처리하기

 

11. 커터 부메랑 공격 가능하게 만들기!

이야 역대급 어려움

왼쪽에서 공격하면, 왼쪽으로 갔다가 오른쪽으로 등의 방향을 구별해야 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class cutWeapon : MonoBehaviour
{
    [SerializeField] private float maxVel = 2;

    private bool kirbyLeft;
    private float timer;
    private float waitingTime;

    private Rigidbody2D rigid;

    private float speed = 1.15f;

    private GameObject kirby;
    private Vector3 destination;
    private SpriteRenderer spriteRenderer;
    public bool isgone = false;
    [SerializeField]private float range = 1f;

    private void Awake()
    {
        timer = 0.0f;
        waitingTime = 0.1f;

        TryGetComponent(out rigid);
        kirby = GameObject.FindGameObjectWithTag("Player");
        spriteRenderer = kirby.GetComponent<KirbyControl>().spriteRenderer;
        if (spriteRenderer.flipX == true) //왼쪽
        {
            kirbyLeft = true;
            destination = kirby.transform.position + new Vector3(-2.5f, 0, 0);
        }
        else
        {
            kirbyLeft = false;
            destination = kirby.transform.position + new Vector3(2.5f, 0, 0);
        }
        Invoke("DestroyCut", 3f);
    }

    private void Update()
    {
        timer += Time.deltaTime;
        if (!isgone)
        {
            Vector3 speed = new Vector3(0, 0, 0);
            transform.position = Vector3.SmoothDamp(transform.position, destination, ref speed, 0.05f);
        }
        if (!isgone && (transform.position.x >= destination.x - range * 0.5f && transform.position.x <= destination.x + range * 0.5f))
        {
            isgone = true;
            if (kirbyLeft)//왼쪽이면
            {
                rigid.velocity = new Vector2(0.3f, 0);
            }
            else //오른쪽이면
            {
                rigid.velocity = new Vector2(-0.3f, 0);
            }
        }
        if (isgone && timer > waitingTime)
        {
            timer = 0;
            float x = rigid.velocity.x * speed;
            rigid.velocity = new Vector2(x, rigid.velocity.y);
            if (!kirbyLeft && rigid.velocity.x >= maxVel)
            {
                rigid.velocity = new Vector2(maxVel, rigid.velocity.y);
            }
            if (kirbyLeft && rigid.velocity.x <= maxVel * -1)
            {
                rigid.velocity = new Vector2(maxVel * -1, rigid.velocity.y);
            }
        }
    }
    private void DestroyCut()
    {
        Destroy(gameObject);
    }
}

커터 무기는 프리팹화 했고, 이를 instantiate로 만들었을시에 목적지와 방향 등을 정의해주었다.

만약 목표 지점까지 안간 상태라면, smoothdamp를 사용해 점점 느려지게 갔고, 0.5만큼의 오차범위 내로 들어오면 isgone을 true로, 반대로 오는 부메랑의 속도를 초기화해주고, 0.5초 (waitingtime)마다 가속도를 더 붙여주었다.

만들어진지 3초 후면 destroy된다.

(개수나 만들어지는 초를 제한하는건 + 던지는 애니메이션은 내일하자)

(약간 부자연스러움)

 

12. 공격에 맞은 적 아파하는 빨강으로 깜빡거리고, 체력이 다 떨어지면 아파하는 모션 그대로 죽기

아파한다

 

728x90