728x90
1. 점수
Canvas 추가
Create Empty
UI -> Slider
UI -> Image
UI -> Text
UI -> Image
Color 255, 0, 0, 0
UI -> Text
알파값 0으로
2. 애니메이션
Create -> Empty
Paratemter -> Trigger
Canvas -> Window -> Animation
녹화버튼
3. 플레이어 피격
C# Script
이펙트 비활성화 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerShot : MonoBehaviour
{
//발포 시간 관련 속성들
public float fireDelayTime; // 발포 주기
public float fireRange; //발포 길이
private float time; //발포 주기 계산 시간
// 발포 피격 관련 속성들
private Ray shootRay = new Ray(); // 레이생성
private RaycastHit shootHit; //레이 충돌 정보
private int shootableMask; // 발포 충돌 레이어 마스크(충돌 레이어 정수값)
public int damagePerShot; //피격 데미지
// 발포 효과 관련 속성들
public ParticleSystem gunParticleSys; //발포 이펙트 파티클 컴포넌트 참조
public LineRenderer fireLine; //발포 라인 효과 (라인랜더러)
public Light faceLight; // 발포 스팟 라이트 효과
public Light gunLight; // 발포 포인트 라이트 효과
public float effectDisplayTime; //발포 효과 재생 시간
public Transform firePos; //발포위치
// Start is called before the first frame update
void Start()
{
// 충돌 레이어 이름으로 충돌 마스크 값을 구함
shootableMask = LayerMask.GetMask("Shootable");
}
// Update is called once per frame
void Update()
{
//시간을 계산함
time += Time.deltaTime;
//마우스 왼쪽 버튼을 누르고
if (Input.GetButton("Fire1") && time >= fireDelayTime)
{
Shot(); //발포 처리
}
if (time >= fireDelayTime * effectDisplayTime)
{
DisableEffects(); // 이펙트 비활성화
}
}
public void DisableEffects()
{
//조명 끄기
gunLight.enabled = false;
faceLight.enabled = false;
//라인 비활성화
fireLine.enabled = false;
}
void Shot()
{
time = 0f;
//이펙트 라이트 on
gunLight.enabled = true;
faceLight.enabled = true;
//발포 파티클 재생
gunParticleSys.Stop();
gunParticleSys.Play();
//라인렌더러 활성화
fireLine.enabled = true;
//라인시작점 인덱스 : 0, 두번쨰 연결점 인덱스 : 1, ......2,3,4
//라인랜더러의 시작점을 총구 위치로 설정
fireLine.SetPosition(0, firePos.position);
//발포 레이 시작 위치 설정
shootRay.origin = firePos.position;
//발포 레이의 방향 설정
shootRay.direction = firePos.forward;
//
if (Physics.Raycast(shootRay, out shootHit, fireRange, shootableMask))
{
//레이가 충돌한 지점까지 라인의 끝점을 설정함
fireLine.SetPosition(1, shootHit.point);
//관통된 게임 오브젝트에 EnemyHealth 컴포넌트 존재하는지 확인함
EnemyHealth health = shootHit.collider.GetComponent<EnemyHealth>();
if (health != null)
{
health.TakeDamage(damagePerShot, shootHit.point);
}
}
else
{
//레이의 충돌이 없으면 레이 방향으로 지정된 발포 길이만큼으로 라인의 끝점을 설정함
fireLine.SetPosition(1, shootRay.origin + shootRay.direction * fireRange);
}
Debug.Log("발포!!!");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
public int startHealth; //시작 체력
public int currentHealth; //현재 체력
public bool isDie; //사망 상태
public Animator animator; //애니메이터
public Slider healthSlider; //체력 슬라이더
public Image damageImage; // 피격 데미지 이미지
private float flashTime = 5f; //피격 데미지 효과 표시 시간
private Color flashColor = new Color(1f, 0f, 0f, 1f); // 붉은색(r,g,b,a)
//컴포넌트 참조
public PlayerMovement movement;
public PlayerShot shot;
private bool damaged; // 피격상태
// Start is called before the first frame update
void Start()
{
currentHealth = startHealth; //시작 체력 설정
}
private void Update()
{
if (damaged)
{
//피격 칼라 효과 처리
damageImage.color = flashColor;
}
else
{
// 피격 칼라 효과 복원
damageImage.color = Color.Lerp(
damageImage.color, Color.clear, flashTime * Time.deltaTime);
}
damaged = false;
}
public void TakeDamage(int damage)
{
damaged = true; //피격 칼라 효고 처리 설정
//체력 감소
currentHealth -= damage;
//체력이 1이고 이미 사망한 상태가 아니라면
if (currentHealth <= 0 && !isDie)
{
Death(); //사망 처리
}
//체력 게이지 처리
healthSlider.value = currentHealth;
}
//몬스터 사망 처리
public void Death()
{
//사망 상태 설정
isDie = true;
//사망 애니메이션 재생
animator.SetTrigger("Die");
shot.DisableEffects(); //발포 이팩트 비활성화
movement.enabled = false; //이동 컴포넌트 비활성화
shot.enabled = false; //발포 컴포넌트 비활성화
}
}
오브젝트 연결
몬스터 공격
C# Scirpt
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAttack : MonoBehaviour
{
public float timeBetweenAttack; //공격주기 시간
public int attackDamage; // 공격 데미지
public Animator animator; //애니메이터
private GameObject player; //플레이어 찾기
private bool playerInRange; //플레이어가 공격범위 안에 있는지 여부
private float time; // 공격 주기 체크용 타임
public EnemyHealth enemyHealth; //몬스터 체력
private PlayerHearlth playerHealth; //플레이어 체력
// Start is called before the first frame update
void Start()
{
//플레이어를 찾아서 참조
player = GameObject.FindGameObjectWithTag("Player");
//플레이어의 체력 컴포넌트를 참조함
playerHealth = player.GetComponent<PlayerHearlth>();
}
public void OnTriggerEnter(Collider collision)
{
if (collision.gameObject == player)
{
playerInRange = true;
}
}
// 몬스터 공격
private void Attack()
{
time = 0;
// 플레이어의 체력이 남아 있으면
if (playerHealth.currentHealth > 0)
{
//플레이어 피격
playerHealth.TakeDamage(attackDamage);
}
}
private void Update()
{
// 시간 계산
time += Time.deltaTime;
// 몬스터의 공격 주기가 되고 플레이어와 충돌 상태라면
if (time >= timeBetweenAttack && playerInRange && enemyHealth.currentHealth > 0)
{
Attack();
}
}
}
몬스터와 플레이어가 닿았다가 떨어질때 메소드 이벤트 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAttack : MonoBehaviour
{
public float timeBetweenAttack; //공격주기 시간
public int attackDamage; // 공격 데미지
public Animator animator; //애니메이터
private GameObject player; //플레이어 찾기
private bool playerInRange; //플레이어가 공격범위 안에 있는지 여부
private float time; // 공격 주기 체크용 타임
public EnemyHealth enemyHealth; //몬스터 체력
private PlayerHealth playerHealth; //플레이어 체력
// Start is called before the first frame update
void Start()
{
//플레이어를 찾아서 참조
player = GameObject.FindGameObjectWithTag("Player");
//플레이어의 체력 컴포넌트를 참조함
playerHealth = player.GetComponent<PlayerHealth>();
}
public void OnTriggerEnter(Collider collision)
{
if (collision.gameObject == player)
{
playerInRange = true;
}
}
//Trigger 충돌 해제 이벤트 메소드
public void OnTriggerExit(Collider collision)
{
//충돌이 일어난 게임오브젝트가 플레이어 게임오브젝트라면
if (collision.gameObject == player)
{
//공격 범위 안에 들어옴
playerInRange = false;
}
}
// 몬스터 공격
private void Attack()
{
time = 0;
// 플레이어의 체력이 남아 있으면
if (playerHealth.currentHealth > 0)
{
//플레이어 피격
playerHealth.TakeDamage(attackDamage);
}
}
private void Update()
{
// 시간 계산
time += Time.deltaTime;
// 몬스터의 공격 주기가 되고 플레이어와 충돌 상태라면
if (time >= timeBetweenAttack && playerInRange && enemyHealth.currentHealth > 0)
{
Attack();
}
}
}
플레이어 사망처리
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//AI(Navigation) 사용
using UnityEngine.AI;
//적군 이동 처리
public class EnemyMovement : MonoBehaviour
{
//공격 대상 (추적대상)
public Transform attackTarget;
//네브메쉬 에이전트 참조
public NavMeshAgent navMeshAgent;
//몬스터 애니메이터
public Animator animator;
public EnemyHealth enemyHealth;
private PlayerHealth playerHealth;
public Rigidbody rigidbody3d;
// Start is called before the first frame update
void Start()
{
//플레이어 게임오브젝트를 찾음 (태그로)
GameObject player = GameObject.FindGameObjectWithTag("Player");
// 츨레이어 체력 컴포넌트 참조
playerHealth = player.GetComponent<PlayerHealth>();
//플레이어를 추적대상으로 설정
attackTarget = player.transform;
}
// Update is called once per frame
void Update()
{
if (enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0)
{
//플레이어를 추적함
navMeshAgent.SetDestination(attackTarget.position);
}
else
{
rigidbody3d.isKinematic = true;
//추적 이동 중단
navMeshAgent.enabled = false;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyGenerator : MonoBehaviour
{
public Transform[] genPositions; //생성 위치들
public GameObject enemyPrefab; // 생성 몬스터 참조
public float genDelayTime; // 생성 주기
public PlayerHealth playerHealth;
// Start is called before the first frame update
void Start()
{
//몬스터 생성 타이머
InvokeRepeating("EnemyGenTimer", 2f, genDelayTime);
}
void EnemyGenTimer()
{
if (playerHealth.currentHealth <= 0) return;
int genIndex = Random.Range(0, genPositions.Length);
Vector3 genPosition = genPositions[genIndex].position;
float x = Random.Range(genPosition.x = 1f, genPosition.x + 1f);
float z = Random.Range(genPosition.x = 1f, genPosition.z + 1f);
genPosition = new Vector3(x, 0f, z);
Instantiate(enemyPrefab, genPositions[genIndex].position, genPositions[genIndex].rotation);
}
}
스코어 올리기
게임매니저 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public static int score = 0;
public Text scoreText;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
scoreText.text = "SCORE : " + score.ToString();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class EnemyHealth : MonoBehaviour
{
//시작 체력
public int startHealth;
//현재체력
public int currentHealth;
//사망 상태
public bool isDie;
//애니메이터 컴포넌트 참조
public Animator animator;
public ParticleSystem hitParticle;
public ParticleSystem deathParticle;
public Renderer bodyRenderer;
// Start is called before the first frame update
void Start()
{
currentHealth = startHealth;
}
//피격 처리 (피격 데미지)
public void TakeDamage(int damage, Vector3 hitPos)
{
currentHealth -= damage;
if (currentHealth <= 0 && !isDie)
{
Death(); //사망 처리
}
if (isDie) return;
hitParticle.transform.position = hitPos;
hitParticle.Play();
}
//몬스터 사망 처리
public void Death()
{
//점수 증가
GameManager.score++;
//사망 상태 설정
isDie = true;
//사망 애니메이션 재상
animator.SetTrigger("Die");
//네비게이션 이동 중단
GetComponent<NavMeshAgent>().isStopped = true;
}
//사망 애니메이션 이벤트 메소드
public void OnDieAnimationEvent()
{
bodyRenderer.enabled = false;
deathParticle.Play();
Destroy(gameObject, deathParticle.main.duration);
}
}
몬스터가 죽을때마다 점수 올라감
게임종료
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public static int score = 0;
public Text scoreText;
private bool isGameOver = false;
public Animator canVasAnimator;
public PlayerHealth playerHealth;
// Update is called once per frame
void Update()
{
scoreText.text = "SCORE : " + score.ToString();
//플레이어가 사망하고
if (playerHealth.isDie && !isGameOver)
{
canVasAnimator.SetTrigger("GameOver");
//5초뒤에 게임 재시작
Invoke("GameReStart", 5f);
isGameOver = true;
}
}
//게임 재시작
public void GameReStart()
{
score = 0; //점수 초기화
//Scene activeScene = SceneManager.GetActiveScene();
//string activeSceneName = activeScene.name;
//아래 한줄과 같은 기능
//현재씬(활성씬)을 재시작함
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
public int startHealth; //시작 체력
public int currentHealth; //현재 체력
public bool isDie; //사망 상태
public Animator animator; //애니메이터
public Slider healthSlider; //체력 슬라이더
public Image damageImage; // 피격 데미지 이미지
private float flashTime = 5f; //피격 데미지 효과 표시 시간
private Color flashColor = new Color(1f, 0f, 0f, 1f); // 붉은색(r,g,b,a)
//컴포넌트 참조
public PlayerMovement movement;
public PlayerShot shot;
private bool damaged; // 피격상태
// Start is called before the first frame update
void Start()
{
currentHealth = startHealth; //시작 체력 설정
}
private void Update()
{
if (damaged)
{
//피격 칼라 효과 처리
damageImage.color = flashColor;
}
else
{
// 피격 칼라 효과 복원
damageImage.color = Color.Lerp(
damageImage.color, Color.clear, flashTime * Time.deltaTime);
}
damaged = false;
}
public void TakeDamage(int damage)
{
damaged = true; //피격 칼라 효고 처리 설정
//체력 감소
currentHealth -= damage;
//체력이 1이고 이미 사망한 상태가 아니라면
if (currentHealth <= 0 && !isDie)
{
Death(); //사망 처리
}
//체력 게이지 처리
healthSlider.value = currentHealth;
}
//몬스터 사망 처리
public void Death()
{
//사망 상태 설정
isDie = true;
//체력 슬라이더 비활성화
healthSlider.gameObject.SetActive(false);
//사망 애니메이션 재생
animator.SetTrigger("Die");
shot.DisableEffects(); //발포 이팩트 비활성화
movement.enabled = false; //이동 컴포넌트 비활성화
shot.enabled = false; //발포 컴포넌트 비활성화
}
}
체력 UI 없어짐 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
public int startHealth; //시작 체력
public int currentHealth; //현재 체력
public bool isDie; //사망 상태
public Animator animator; //애니메이터
public Slider healthSlider; //체력 슬라이더
public Image damageImage; // 피격 데미지 이미지
private float flashTime = 5f; //피격 데미지 효과 표시 시간
private Color flashColor = new Color(1f, 0f, 0f, 1f); // 붉은색(r,g,b,a)
//컴포넌트 참조
public PlayerMovement movement;
public PlayerShot shot;
private bool damaged; // 피격상태
// Start is called before the first frame update
void Start()
{
currentHealth = startHealth; //시작 체력 설정
}
private void Update()
{
if (damaged)
{
//피격 칼라 효과 처리
damageImage.color = flashColor;
}
else
{
// 피격 칼라 효과 복원
damageImage.color = Color.Lerp(
damageImage.color, Color.clear, flashTime * Time.deltaTime);
}
damaged = false;
}
public void TakeDamage(int damage)
{
damaged = true; //피격 칼라 효고 처리 설정
//체력 감소
currentHealth -= damage;
//체력이 1이고 이미 사망한 상태가 아니라면
if (currentHealth <= 0 && !isDie)
{
Death(); //사망 처리
}
//체력 게이지 처리
healthSlider.value = currentHealth;
}
//몬스터 사망 처리
public void Death()
{
//사망 상태 설정
isDie = true;
//체력 슬라이더 비활성화
healthSlider.gameObject.SetActive(false);
//현재 체력 슬라이더의 부모 게임오브젝트의 Transform을 참조
//Transform.parent <- 부모 접근 속성
Transform healthUITransform = healthSlider.transform.parent;
//체력 표시용 UI 비활성화
healthUITransform.gameObject.SetActive(false);
//사망 애니메이션 재생
animator.SetTrigger("Die");
shot.DisableEffects(); //발포 이팩트 비활성화
movement.enabled = false; //이동 컴포넌트 비활성화
shot.enabled = false; //발포 컴포넌트 비활성화
}
}
'Unity' 카테고리의 다른 글
[유니티] RPG 게임 만들기2 (0) | 2021.05.28 |
---|---|
[유니티] 3D 슈팅게임 3 (0) | 2021.05.28 |
[유니티] 3D 슈팅게임 만들기 (0) | 2021.05.21 |
[유니티] 네이게이션 (0) | 2021.05.20 |
[유니티]UI (드롭박스) (0) | 2021.05.20 |
댓글