[SKKU DT] 12일차 -FPS 게임 만들기(4) -체력 바 UI 구현
2023. 11. 14. 18:20ㆍSKKU DT
728x90
반응형
체력 바에 UI - 슬라이더를 사용한다.
Transform 값을 0으로 바꾼다.
Fill의 색도 바꾼다.
Slider의 Value로 조절할 수 있다.(현재 체력 / 전체 체력)
PlayerMove 스크립트에서 체력을 적용한다.
using UnityEngine.UI;로 UI 네임스페이스 사용
최대 체력, 체력 슬라이더 변수 추가
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;
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;
}
Debug.Log("플레이어 체력: " + hp);
}
}
적 체력 바 만들기
-새 캔버스 만들고 [RenderMode] - [World Space]
Enemy 오브젝트 밑에 적 캔버스 위치
캔버스 스케일 줄이기
EnemyFSM 스크립트에서 적 체력 바 조절
using UnityEngine.UI; 추가, 적 체력 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyFSM : MonoBehaviour
{
//적 상태 상수 6개 생성
enum EnemyState
{
Idle,
Move,
Attack,
Return,
Damaged,
Die
}
//적 상태 변수
EnemyState m_State;
//플레이어 발견 범위
public float findDistance = 10f;
//플레이어 Transform Component 적이 많이 생성되면 끌어 넣는게 비어있을 수 있다. Find로 찾아서 적용
Transform player;
//공격 범위
public float attackDistance = 4f;
//적 이동 속도
public float moveSpeed = 5f;
//적 캐릭터 컨트롤러 컴포넌트
CharacterController cc;
//적 공격 누적 시간
float currentTime = 0;
//적 공격 딜레이 시간
float attackDelay = 2f;
//적 공격력
public int attackPower = 10;
//적이 다시 되돌아갈 초기 위치 저장
Vector3 originPos;
//적 이동 가능 범위
public float moveDistance = 20f;
//적 체력 설정
public int hp = 50;
//적 최대 체력
public int maxHP = 50;
//슬라이더 변수 가져오기
public Slider enemyHPSlider;
void Start()
{
//플레이어 Transform Component 할당
player = GameObject.Find("Player").transform;
//최초의 적 상태를 대기로 설정
m_State = EnemyState.Idle;
//적 캐릭터 컨트롤러 컴포넌트 할당
cc = GetComponent<CharacterController>();
//적의 초기 위치 저장
originPos = transform.position;
}
void Update()
{
//적의 상태를 체크해서 상태별로 정해진 기능을 수행 Switch문 / Damaged와 Die는 AnyState이기 때문에 case에 들어가지 않는다.
switch (m_State)
{
case EnemyState.Idle:
Idle();
break;
case EnemyState.Move:
Move();
break;
case EnemyState.Attack:
Attack();
break;
case EnemyState.Return:
Return();
break;
}
//적 슬라이더에 값 반영
enemyHPSlider.value = (float)hp / (float)maxHP;
}
void Idle()
{
//만약 플레이어와 적의 거리가 발견 범위 이내라면 Move 상태로 전환
if(Vector3.Distance(transform.position, player.position) < findDistance)
{
m_State = EnemyState.Move;
Debug.Log("발견!");
}
}
void Move()
{
//만약 현재 위치와 초기 위치 거리가 이동 가능 범위보다 크면 복귀
if(Vector3.Distance(transform.position, originPos) > moveDistance)
{
m_State = EnemyState.Return;
Debug.Log("상태 전환");
}
//만약 플레이어와 적의 거리가 공격 범위보다 크다면 플레이어를 향해 이동
else if (Vector3.Distance(transform.position, player.position) > attackDistance)
{
//이동 방향
Vector3 dir = (player.position - transform.position).normalized;
//이동
cc.Move(dir * moveSpeed * Time.deltaTime);
}
else
{
m_State = EnemyState.Attack;
Debug.Log("공격!");
//공격이 바로 안되므로 공격 딜레이 시간 만큼 미리 진행을 시켜놓아야 한다.
currentTime = attackDelay;
}
}
void Attack()
{
//플레이어와 적의 거리가 공격 범위 이내라면 공격
if(Vector3.Distance(transform.position, player.position) < attackDistance)
{
//일정 시간마다 플레이어 공격
currentTime += Time.deltaTime;
if(currentTime > attackDelay)
{
player.GetComponent<PlayerMove>().DamageAction(attackPower);
print("공격!");
currentTime = 0;
}
}
//그렇지 않다면, Move();
else
{
m_State = EnemyState.Move;
Debug.Log("이동");
currentTime = 0;
}
}
void Return()
{
//오리지널 방향으로 돌아가기 특정 좌표값보다 범위로 나타내는게 에러가 덜 날 가능성이 높다.
if(Vector3.Distance(transform.position, originPos) > 0.1f)
{
//방향 구하기 (목적지 - 내 위치)
Vector3 dir = (originPos - transform.position).normalized;
//이동하기
cc.Move(dir * moveSpeed * Time.deltaTime);
}
else //그렇지 않다면 적 위치를 초기 위치로 조정하고, 대기 상태로 전환한다.
{
transform.position = originPos;
m_State = EnemyState.Idle;
Debug.Log("상태 전환: Return -> Idle");
}
}
//데미지 처리 Coroutine 함수
IEnumerator DamageProcess()
{
//피격 모션만큼 기다림 애니메이션 고려
yield return new WaitForSeconds(0.5f);
//이동 상태 전환
m_State = EnemyState.Move;
}
void Damaged()
{
//피격 코루틴 실행
StartCoroutine(DamageProcess());
}
//데미지 실행 함수
public void HitEnemy(int hitPower)
{
//적이 피격 상태이면 플레이어를 때릴 수 없게
if(m_State == EnemyState.Damaged)
{
return;
}
//플레이어의 공격력만큼 적 체력 감소
hp -= hitPower;
//적 체력이 0보다 크면 피격
if(hp > 0)
{
m_State = EnemyState.Damaged;
Damaged(); //코루틴 호출
Debug.Log("적 체력 표시: " + hp);
}
//0보다 작으면 죽음
else
{
m_State = EnemyState.Die;
Debug.Log("죽음");
Die();
}
IEnumerator DieProcess()
{
//적 캐릭터 컨트롤러 컴포넌트 비활성화
cc.enabled = false;
//2초 대기
yield return new WaitForSeconds(3f);
//적 제거
Destroy(gameObject);
}
void Die()
{
//실행 중인 이전 Coroutine 중지
StopAllCoroutines();
//죽음 Coroutine 실행
StartCoroutine(DieProcess());
}
}
}
적 체력 바가 계속 나를 바라보게 하기
Billboard 스크립트 생성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Billboard : MonoBehaviour
{
public Transform target;
void Update()
{
transform.forward = target.forward;
}
}
728x90
반응형
'SKKU DT' 카테고리의 다른 글
[SKKU DT] 13일차 -FPS 게임 만들기(6) -좀비 모델링 적용, 애니메이션 적용, 로비 씬 (0) | 2023.11.15 |
---|---|
[SKKU DT] 13일차 -FPS 게임 만들기(5) -UI 데미지 입을 때, Ready,Go 텍스트 (0) | 2023.11.15 |
[SKKU DT] 12일차 -FPS 게임 만들기(3) -적 만들기, 적 구현 (0) | 2023.11.14 |
[SKKU DT] 11일차 -FPS 게임 만들기(2) -무기 만들기(폭탄, 총) (0) | 2023.11.13 |
[SKKU DT] 11일차 -FPS 게임 만들기(1) -캐릭터 이동 (0) | 2023.11.13 |