[SKKU DT] 13일차 -FPS 게임 만들기(5) -UI 데미지 입을 때, Ready,Go 텍스트

2023. 11. 15. 12:55SKKU DT

728x90
반응형

데미지 입을 때 적용할 이미지를 위해 UI - Image 생성

Shift + Alt 누르면 화면에 꽉 차게 설정할 수 있다.

 

 


 

 

플레이어의 체력이 들어있는 PlayerMove 스크립트에서 UI Image 제어를 한다.

Coroutine 함수를 써서 1초정도 나왔다가 기다려 후 없어지는 방식을 사용한다.

체력이 음수일 때는 효과가 나올 필요가 없다.

IEnumerator PlayBloodEffect() 생성, StartCoroutine(PlayBloodEffect()); 코루틴 실행

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

public class PlayerMove : MonoBehaviour
{
    public float moveSpeed = 7f;
    //캐릭터 컨트롤러 컴포넌트 변수
    CharacterController cc;
    //중력 변수
    float gravity = -20f;
    //수직 속력 변수 초기화
    float yVelocity = 0;
    //점프력 변수
    public float jumpPower = 7f;
    //점프 상태 변수 처음엔 점프 안하므로 0
    int isJumping = 0;
    //플레이어 체력 변수
    public int hp = 100;
    //최대 체력
    int maxHP;
    //체력 슬라이더 변수
    public Slider hpSlider;
    //블러드 효과 이미지 오브젝트 형태로 가져오기
    public GameObject bloodImage;

    private void Start()
    {
        //컴포넌트 변수는 Start 함수에서 할당을 해주어야 한다.
        cc = GetComponent<CharacterController>();
        maxHP = hp;
    }
    void Update()
    {
        //키보드 입력 받기
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        //이동 방향 설정
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        dir = dir.normalized;

        //바라보는 기준 방향으로 움직이기
        dir = Camera.main.transform.TransformDirection(dir);

        //캐릭터가 바닥에 착지 했다면 = 바닥면이 닿았다면 상태 초기화
        if(cc.collisionFlags == CollisionFlags.Below)
        {
            isJumping = 0;
            yVelocity = 0;
        }

        //점프 후 중력값 적용을 위해 중력 값 적용 위에 쓴다. Space 누르면 점프
        if (Input.GetButtonDown("Jump"))
        {
            if(isJumping == 0 || isJumping == 1)//만약 0또는 1인 상태이면 뛴다.
            {
                yVelocity = jumpPower;
                isJumping += 1;
            }
        }

        //수직 속도에 중력 값 적용
        yVelocity += gravity * Time.deltaTime;
        dir.y = yVelocity;

        //이동
        cc.Move(dir * moveSpeed * Time.deltaTime);

        //현재 체력을 슬라이더의 Value에 반영
        hpSlider.value = (float)hp / (float)maxHP;
    }
    //플레이어 피격 함수
    public void DamageAction(int damage) //argument로 int 형의 damage를 받아 온다.
    {
        //적의 공력력 만큼 플레이어 체력 감소
        hp -= damage;
        //체력이 음수이면 0으로 초기화
        if(hp < 0)
        {
            hp = 0;
        }
        else
        {
            //체력이 양수일 때 피격 효과 출력
            StartCoroutine(PlayBloodEffect());
        }
        Debug.Log("플레이어 체력: " + hp);
    }
    //피격 효과 Coroutine 함수 생성
    IEnumerator PlayBloodEffect()
    {
        //피격 효과 활성화
        bloodImage.SetActive(true);
        //0.3초 대기
        yield return new WaitForSeconds(0.3f);
        //피격 효과 비활성화
        bloodImage.SetActive(false);
    }
}

 

 


 

 

상황에 맞는 텍스트 표시하기

 

 

GameManager 스크립트 생성

싱글 톤 구현 다른 클래스의 인스턴들이 공유를 할 수 있다. Awake 함수 사용

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

public class GameManager : MonoBehaviour
{
    //게임 매니저 가져와서 gm 변수 설정
    public static GameManager gm;

    private void Awake()
    {
        if(gm == null)
        {
            gm = this;  //없으면 싱글톤 할당을 해서 적용한다.
        }
    }
    //게임 상태 상수. Ready라는 상태를 모든 스크립트가 알아야함
    public enum GameState
    {
        Ready,
        Go,
        GameOver
    }
    //GameState 변수 선언. gState에 따라서 효과 적용
    public GameState gState;
    //UI 오브젝트 변수 생성
    public GameObject gameLabel;
    //게임 상태 텍스트 가져오기. 컴포넌트 변수는 Start에서 할당을 해주어야 함.
    Text gameText;
    void Start()
    {
        //초기 상태를 준비로 설정
        gState = GameState.Ready;
        gameText = gameLabel.GetComponent<Text>();
        gameText.text = "Ready";
    }
    void Update()
    {

    }
    IEnumerator ReadyToStart()
    {
        //2초 대기
        yield return new WaitForSeconds(2f);
        //Go
        gameText.text = "Go!";
        //대기
        yield return new WaitForSeconds(0.5f);
        //텍스트 비활성화
        gameLabel.SetActive(false);
        //상태 변경
        gState = GameState.Go;
    }
}

 


 

 

응용(적 랜덤 생성, BillBoard 스크립트 수정)

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

public class EnemyManager : MonoBehaviour
{
    //현재 시간
    float currentTime = 0;
    //생성 시간
    float createTime = 5f;
    //적 오브젝트 받아오기
    public GameObject Enemies;
    void Start()
    {
        
    }
    void Update()
    {
        currentTime += Time.deltaTime;
        if(currentTime > createTime)
        {
            Instantiate(Enemies, new Vector3(Random.Range(-43.5f, 43.5f), 1, Random.Range(-43.5f, 43.5f)), Quaternion.identity);
            currentTime = 0;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Billboard : MonoBehaviour
{
    Transform camTransform;
    private void Start()
    {
        camTransform = GameObject.Find("Main Camera").transform;
    }
    void Update()
    {
        transform.forward = camTransform.forward;
    }
}

 

 


 

 

PlayerMove 스크립트에서 Go 일 때만 움직이게 하기( CamRotate 스크립트의 Update함수 가장 위에도 복사 붙여넣기 한다.)

if(GameManager.gm.gState != GameManager.GameState.Go)
{
    return;  //함수 바로 끝내버려 Update 전체 종료
}

 

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

public class PlayerMove : MonoBehaviour
{
    public float moveSpeed = 7f;
    //캐릭터 컨트롤러 컴포넌트 변수
    CharacterController cc;
    //중력 변수
    float gravity = -20f;
    //수직 속력 변수 초기화
    float yVelocity = 0;
    //점프력 변수
    public float jumpPower = 7f;
    //점프 상태 변수 처음엔 점프 안하므로 0
    int isJumping = 0;
    //플레이어 체력 변수
    public int hp = 100;
    //최대 체력
    int maxHP;
    //체력 슬라이더 변수
    public Slider hpSlider;
    //블러드 효과 이미지 오브젝트 형태로 가져오기
    public GameObject bloodImage;

    private void Start()
    {
        //컴포넌트 변수는 Start 함수에서 할당을 해주어야 한다.
        cc = GetComponent<CharacterController>();
        maxHP = hp;
    }
    void Update()
    {
        //게임 중인 상태에서만 조작 싱글톤인 GameManager를 이름 그대로 가져올 수 있다.
        if(GameManager.gm.gState != GameManager.GameState.Go)
        {
            return;  //함수 바로 끝내버려 Update 전체 종료
        }
        //키보드 입력 받기
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        //이동 방향 설정
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        dir = dir.normalized;

        //바라보는 기준 방향으로 움직이기
        dir = Camera.main.transform.TransformDirection(dir);

        //캐릭터가 바닥에 착지 했다면 = 바닥면이 닿았다면 상태 초기화
        if(cc.collisionFlags == CollisionFlags.Below)
        {
            isJumping = 0;
            yVelocity = 0;
        }

        //점프 후 중력값 적용을 위해 중력 값 적용 위에 쓴다. Space 누르면 점프
        if (Input.GetButtonDown("Jump"))
        {
            if(isJumping == 0 || isJumping == 1)//만약 0또는 1인 상태이면 뛴다.
            {
                yVelocity = jumpPower;
                isJumping += 1;
            }
        }

        //수직 속도에 중력 값 적용
        yVelocity += gravity * Time.deltaTime;
        dir.y = yVelocity;

        //이동
        cc.Move(dir * moveSpeed * Time.deltaTime);

        //현재 체력을 슬라이더의 Value에 반영
        hpSlider.value = (float)hp / (float)maxHP;
    }
    //플레이어 피격 함수
    public void DamageAction(int damage) //argument로 int 형의 damage를 받아 온다.
    {
        //적의 공력력 만큼 플레이어 체력 감소
        hp -= damage;
        //체력이 음수이면 0으로 초기화
        if(hp < 0)
        {
            hp = 0;
        }
        else
        {
            //체력이 양수일 때 피격 효과 출력
            StartCoroutine(PlayBloodEffect());
        }
        Debug.Log("플레이어 체력: " + hp);
    }
    //피격 효과 Coroutine 함수 생성
    IEnumerator PlayBloodEffect()
    {
        //피격 효과 활성화
        bloodImage.SetActive(true);
        //0.3초 대기
        yield return new WaitForSeconds(0.3f);
        //피격 효과 비활성화
        bloodImage.SetActive(false);
    }
}

 

 

 

728x90
반응형