본문 바로가기

GAME

[Unity2D]조사액션 / 조사창 구현

728x90

 

유니티 기초 - B23 쯔꾸르식 액션 구현하기 - 조사액션

유니티 기초 - B22 대화창 UI구축하기

를 참고하여 만들었습니다.

 

골드메탈님은 쯔꾸르? 이걸 쓰리디라고 하나.. 를 만드셨지만 

제가 만들 게임은 찐2D여서 약간 변형하여 작성하였습니다. 

 

조사액션

일단 조사가 가능한 오브젝트를 Object라는 Layer로 지정합니다.

 

저는 NPC 1명과, 감옥 쇠창살/문 3개를 object로 두었습니다. 

 

일단 3개는 다른 성질을 가졌는데, 

내 계획으로 

NPC / 쇠창살 : 통과 불가 ( is Trigger : false) + 밀려나거나 하지 않음 (rigidbody (type) : Kinematic)

또한 NPC는 쇠창살 안에 있는데 물리충돌이 발생하지 않아야함( 원래대로라면 쇠창살에 밀려나 밖으로 나가짐)

문 : 통과 가능 ( is Trigger : true) + 밀려나지 않음 (rigidbody (type) : Kinematic)

 

 

물체를 감지하기위해 Ray를 사용합니다.

일단 캐릭터가 바라보는 방향으로 ray를 그려야하므로 캐릭터 방향을 표현해주는 direction변수를 만듭니다.

캐릭터가 오른쪽을 보면 1, 왼쪽을 보면 -1을 저장하도록 

Update()에 있던 방향키부분을 변경하도록 합니다

    int direction;
    
    
    private void Update(){
    
        //Direction Sprite
        if(Input.GetButton("Horizontal"))
        {
            if(Input.GetAxisRaw("Horizontal") == -1){
                spriteRenderer.flipX=true;
                direction=-1;

            }
            else{
                spriteRenderer.flipX=false;
                direction=1;

            }
        }
    
    }

 

이제 탐지할수 있는 범위를 지정하기 위해 탐지거리를 저장한 변수를 선언합니다.

float detect_range=1.5f;


private void FixedUpdate(){

		//조사액션
        Debug.DrawRay(rigid.position, new Vector3(direction*detect_range,0,0), new Color(0,0,1));

}

이정도 거리에 있으면 탐지할 수 있도록 1.5f정도로 설정하였습니다

 

이제 실제로 조사한 물체를 저장해서 이름을 출력해봅시다

    GameObject scanObject;
    
    
    private void FixedUpdate()
    {
    
        //조사액션
        Debug.DrawRay(rigid.position, new Vector3(direction*detect_range,0,0), new Color(0,0,1));
        
        //Layer가 Object인 물체만 rayHit_detect에 감지 
        RaycastHit2D rayHit_detect = Physics2D.Raycast(rigid.position, new Vector3(direction,0,0), detect_range, LayerMask.GetMask("Object"));

		//감지되면 scanObject에 오브젝트 저장 
        if(rayHit_detect.collider != null)
        {
            scanObject = rayHit_detect.collider.gameObject;
            Debug.Log(scanObject.name);

        }else{
            scanObject = null;
        }
        
	}

 

이름이 정상적으로 출력됩니다.

 

조사액션이니 "스페이스 바"를 눌렀을 때만 이름이 출력되도록 해봅시다

    void Update(){

        // 버튼에서 손을 떄는 등의 단발적인 키보드 입력은 FixedUpdate보다 Update에 쓰는게 키보드 입력이 누락될 확률이 낮아짐


        //Jump
        if(Input.GetButtonDown("Jump") && !animator.GetBool("isJumping"))
        {

            if(scanObject!=null) //조사할게 있으면 이름출력(점프는 안됨)
            {
                Debug.Log(scanObject.name);
            }
            else{ //아니면 점프
                rigid.AddForce(Vector2.up* jumpPower , ForceMode2D.Impulse);
                animator.SetBool("isJumping",true);
            }
        }
        
   }

 

 

여기서 문제점은 

is Trigger가 true인 경우 rayHit가 발동하지 않는다

Edit -> Project Setting ->Physics2D -> Queries Hit Triggers 체크

해주면 이제 됩니다

 

 

대화창 

대화창을 구현하기위해서는 UI 캔버스를 만들어야하는데 이미 이어서 하기때문에 캔버스가 존재합니다

캔버스에서 Pixel Perfect를 체크

 

다음 두개의 이미지를 이용합니다. 

대화창
대화 넘기는 커서(?)

 

1 . 대화창 생성

대화창을 sprite에 넣는데 간단한 설정이 필요합니다.

Sprite Editor에서 Border를 이용해 모서리를 제외해 준 후 Apply를 누릅니다

 

 

이제 새로운 UI Image오브젝트를 만든 후 스프라이트를 적용하고 

Image Type : Sliced를 적용합니다.

 

* 여러분은 화면 Scene이랑 Game화면 분할해놓고 UI크기 정하지 마세요... ㄱ- 

분할해서 설정해놨더니 크게 보니까 개작더라고요 

 

이런 설정을 완료해주면 대화창의 크기를 늘려도 대화창이미지가 깨지지 않습니다.

는 근데 너무 구려서 나중에 이미지 수정해야겠다

 

Alt를 누른후 stretch의 양옆을 눌러줍니다 

 

적절하게 여백들을 Left/Right/Pos Y/Height등에 넣어주면 됩니다 

 

2. 대화창 안의 대사

 UI 이미지 내부에 자식으로 Text를 생성해줍니다.

 

 

폰트나 글자크기등을 적절하게 설정해주고

shift / Alt를 이용해서 엥커를 맨왼쪽으로 잡고 middle , stretch로 설정해줍니다

 

맨 왼쪽은 캐릭터의 초상화를 넣어야하므로 왼쪽에 60정도의 여백을 넣어줍니다 

두줄을 입력한후 Height도 적절하게 잡아줍니다 (저는 40임)

 

 

 

3. 데이터 전달

 

조사액션으로 조사하여 콘솔창에 띄웠던 정보를 대화창에 띄워봅시다.

UI이므로 GameManager.cs에서 진행합니다.  

txtUI 변수와 scanObject를 저장할 변수 2개가 필요합니다.

 

GameManager.cs

    //대화창 
    public Text UITalkText;
    public GameObject scanObject;

 

전달받은 scanObject를 받아서 txt에 전달하는 함수를 만듭니다. 

    public void Action(GameObject scanObj)
    {
        scanObject = scanObj;
        UITalkText.text = "이것은 "+scanObject.name+"이다.";
    }

 

 

이제 이 함수를 PlayerMove.cs에서 스페이스 바를 누를때 콘솔출력 코드대신 사용해주면됩니다.

PlayerMove.cs

private void Update(){

        //Jump
        if(Input.GetButtonDown("Jump") && !animator.GetBool("isJumping"))
        {

            if(scanObject!=null)
            {
                gameManager.Action(scanObject);
                //Debug.Log(scanObject.name); -> 주석처리후 대신 Action함수를 실행
            }
            else{
                rigid.AddForce(Vector2.up* jumpPower , ForceMode2D.Impulse);
                animator.SetBool("isJumping",true);
            }
        }
}

플레이어가 조사해서 저장해둔 오브젝트를 넘겨주도록 코드를 구성합니다.

 

이제 유니티내에서 public으로 선언한 txt를 드래그해서 초기화해줍니다.

 

 

 

 

 

4. 상태 전환

액션을 취할때만 대화창이 뜨도록 바꾸어봅시다

 

대화창이 활성화 되었는지 알아보는 bool 변수를 생성하고

대화창 이미지를 변수로 생성해 준 후 SetActive를 이용하여 Action()이 실행될때만 뜨도록 바꿉시다 

    //대화창 UI 및 변수 
    public GameObject talkPanel;
    public Text UITalkText;
    public GameObject scanObject;
    public bool isAction; //대화창 활성화 상태 
    
    
public void Action(GameObject scanObj)
    {
        if(isAction) // 실행중인데 또 액션을 실행한경우 -> 이미 true인경우
        {
            isAction=false; //false로 변경

        }
        else //실행중 -> 대화창 띄우기 
        {
            isAction = true;
            scanObject = scanObj;
            UITalkText.text = "이것은 "+scanObject.name+"이다.";
        }

        talkPanel.SetActive(isAction); //대화창 활성화 상태에 따라 대화창 활성화 변경
    }

즉, 스페이스바를 다시 누르면 대화창이 내려가게됩니다.

 

대화창을 이용한 조사액션을 실행중 일때는 움직임을 제한하도록 합시다

FixedUpdate에 이동을 다음과 같이 변경해주고 

float h = gameManager.isAction? 0 :Input.GetAxisRaw("Horizontal");   

Update에 방향전환시 캐릭터의 방향을 전환시키는 코드에도 다음과 같이 추가하여 

방향전환도 막아보도록 합시다

//Direction Sprite
        if(gameManager.isAction==false && Input.GetButton("Horizontal"))
        {
            if(Input.GetAxisRaw("Horizontal") == -1){
                spriteRenderer.flipX=true;
                direction=-1;
                //Debug.Log(direction);
            }
            else{
                spriteRenderer.flipX=false;
                direction=1;
                //Debug.Log(direction);
            }
        }

 

* 여기서 움직임을 제한했을 때 마찰력이 부족해서 캐릭터가 밀려나는 현상이 발생하여

저는 Platform의 마찰력을 3으로 증가시켜주었습니다. 

Project->Physical Materail

 

 

 

4.  애니메이션 (커서 위아래로 움직이기 )

이제 대화를 넘기는 버튼(사과)를 패널이미지 안에 넣어서 생성한다음 앵커를 이용해 자리를 잡아줍니다.

 

 

이제 저 사과에 애니메이션을 추가하여 다음으로 넘기는 키인것을 알려줍시다. (Pos Y = 10으로 수정)

 

인스펙터 창에서 animator추가

 

Project->Animation폴더에서 

Animation controller : Apple_cursor 생성 -> 인스펙터 animator에 추가

 

Animation : Cursor_move 생성

 

Apple_cursor 애니메이션 컨트롤러 더블클릭 후 

create state -> empty 추가후

이름 Move로 변경하고 Motion에 만들어둔 Cursor_move 적용

 

 

Animation창을 띄운 후 

Add Property -> Anchored Position 추가

위아래로 흔들리게 만들기 위해 Anchored Position.y를 

10->15->10 -> 15으로 애니메이션 생성

 

Loop Time에 체크해줍니다. 

 

그리고 대화창을 비활성화 해줍니다.

 

그 후 시작하면

사과가 움직입니다 

 

 

 

참고영상

youtu.be/bZVa6C6vRBQ

 

youtu.be/jVBiGhlwhZg

 

728x90

'GAME' 카테고리의 다른 글

[Unity2D] 퀘스트 시스템 구현  (0) 2020.08.31
[Unity2D] 대화창 구현  (0) 2020.08.29
[Unity2D] 기초2D게임 만들기  (0) 2020.08.07
[Unity2D] 적 몬스터 구현하기  (1) 2020.08.01
[Unity2D] 타일맵 Platform 만들기  (0) 2020.08.01