프롭
물리적 기능 필요하면 뭐 넣는다? RigidBody!!!
튕겨 나갈 수 있도록 RigidBody를 넣기
Prop 스크립트 추가
* 기능
- 프롭은 기본적으로 체력을 가지고 있어서 일정 이상의 데미지를 받으면 파괴가 되어야 함
- 자기 자신이 파괴되었을 때 게임 매니저에게 자기 자신이 파괴 되었다는 것을 알리고 점수를 추가해줘야 함
- 자기 스스로 실행시키는 것이 아니라 외부에서 데미지를 주는 친구가 프롭에게 가서 TakeDamage 라는 함수를 발동시켜서 프롭에게 데미지를 줄 것임
Instantiate();
이 안에 원본 게임오브젝트를 넣어주면 그 원본 게임오브젝트를 새로 하나 복사해줌
새로 하나 찍어낼 때 옵션을 줄 수도 있음 (position, rotation)
위치 지정 안하면 랜덤한 위치나 미리 지정된 원점으로 이동
Prop Scripts
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Prop : MonoBehaviour
{
//자기 자신 파괴될 때 마다 올라갈 점수
public int score = 5;
//프롭이 파괴될 때 파티클에서 하나 찍어낼 것
public ParticleSystem explosionParticle;
//hp가 작아졌을 때 프롭이 파괴가 됨
public float hp = 10f;
public void TakeDamage(float damage)
{
hp -= damage;
if(hp<=0)
{
ParticleSystem instance =Instantiate(explosionParticle, transform.position, transform.rotation);
AudioSource explosionAudio = instance.GetComponent<AudioSource>();
explosionAudio.Play();
Destroy(instance.gameObject, instance.duration);
//프롭이 많이 생길건데 매번 프롭을 Destroy하고 다음 라운드에 프롭을 다시 수백개씩 생성하면
//렉이 걸릴 수 있음
//따라서 프롭을 껐다가 다시 켜는 방법으로 재활용 할 것임!
//프롭은 파괴 되는 것이 아니라 off되는 것임
gameObject.SetActive(false);
}
}
}
데미지 시스템
Ball이 폭발할 때 자기 주변 반경에 있는 모든 prop들을 가져와서 데미지를 주고 동시에 그 친구들에게 힘을 줘서 밀어내야 함
-> 1. Ball을 중심으로 폭발 반경을 구로 그린다.
2. 해당되는 모든 프롭들을 가져와서 만약 Prop이라는 스크립트를 가지고 있으면
그 안의 TakeDamage 함수를 발동시킨다.
뭐 부터 해야하나?
Ball이 폭발 반경 안에 있는 prop들을 어떻게 구별하나?
주변에 콜라이더가 굉장히 많은데 어떻게 prop을 구별하는가? Layer 사용!!!
Tag , Layer 차이?
Tag : 일반적인 경우에 사용, 1:1 비교만 가능
Layer : 물리처리에 주로 사용, 한번에 여러개 필터링 가능
LayerMask는 한 번에 여러개 선택해서 필터링 가능
여기서는 Prop만 체크하기
부딪혔을 때 한가지 처리를 더 해야함.
1) 나의 위치를 기준으로 가상의 구를 그려줘야함
이 기능은 기본적으로 물리 기능에 속함.
즉, 가상의 구를 그려서 겹치는 모든 친구를 가져오는 것을 가져오는 것은 Physics라는 물리 집합에 들어가있음
Physics : 유니티에서 지원하는 물리 관련 기능들이 들어가있는 함수집합
Physics.OverlapSphere : 위치를 지정해주면(여기서는 구의 중심과 반지름) 거기에 겹치는 모든 콜라이더들을 배열로 다 가져와줌
private void OnTriggerEnter(Collider other) {
//성능 아끼기 위해 필터링
//OverlapSphere은 Collider들을 반환함!
Collider[] colliders =Physics.OverlapSphere(transform.position, explosionRadius, whatIsProp);
2) 데미지 계산 함수 만들기
데미지를 차등으로 주려고 함 (폭발의 중심지에 가까울수록 많이(100%), 원의 가장자리에 갈수록 적게(0%))
알아야 할 것은 나의 위치에서 상대방까지의 거리(x)가 아니라
상대방이 원의 가쪽에서 얼마만큼 안쪽으로 들어왔는지(radius-x).
왜? 원 바깥쪽에서 원의 안쪽으로 들어올 수록 damage를 더 많이 받기 때문.
x=0 이면 파란색 점이 정 중앙에 있어서 1.0, x=radius이면 0
주의할 점: 폭발 반경에 걸치는 collider가 있음
collider의 실제 위치는 가상의 구 안에 들어오지 않는데 양쪽으로 부피가 있어서 겹치는 경우.
이 때 겹치는 건 - %가 됨.
Damage가 - 라는 것은 체력이 오히려 회복된다는 얘기!
Ball.cs 안의 CalculateDamage함수
// 이 함수는 어떤 위치를 주면 내 위치에서 그 위치사이까지
// 거리를 재서 데미지를 얼마만큼 받을지 결정할 것임
//targetPosition은 상대방 위치
private float CalculateDamage(Vector3 targetPosition)
{
//나의 위치에서 상대방까지의 거리를 Vector3 x, y, z로 쪼갬
// (x, y, z)로 되어 있음.
Vector3 explosionToTarget = targetPosition - transform.position;
//Vector3는 내장 기능으로써 자기 자신의 길이를 가져다줌(피타고라스 법칙 사용해서 실제 하나의 숫자로 뽑아내줌)
//magnitude는 벡터의 길이
//폭발의 중심지와 상대방 사이의 거리
float distance = explosionToTarget.magnitude;
//알아야 할 것은 나의 위치에서 상대방까지의 거리가 아니라
//원의 가장자리에서 얼마나 안쪽으로 들어가있냐 알아야함
float edgeToCenterDistance = explosionRadius - distance;
float percentage = edgeToCenterDistance / explosionRadius;
//최종 데미지
float damage = maxDamage * percentage;
//- damage : 체력 회복 방지
// 두 수를 넣었을 때 그 중에서 큰 값을 반환
damage = Mathf.Max(0,damage);
return damage;
}
3) CalculateDamage 함수 사용해서 각각 colliders들 위치 파악 + 그 colliders는 어느 만큼 데미지 입어야 하는지 계산
Rigidbody.AddExplosionForce() :
어떤 지점의 폭발의 위치와 폭발력, 반경 지정해주면 나 자신의 위치가 폭발의 원점으로부터 얼만큼 떨어져있는지 등을 계산해서 스스로 튕겨나가는 작용 적용해줌
Ball.cs 안의 OnTriggerEnter 함수
private void OnTriggerEnter(Collider other) {
//성능 아끼기 위해 필터링
//OverlapSphere은 Collider들을 반환함!
Collider[] colliders =Physics.OverlapSphere(transform.position, explosionRadius, whatIsProp);
for(int i=0; i<colliders.Length; i++ )
{
//데미지 주기 전에 상대방 Rigidbody 가져오기
Rigidbody targetRigidbody = colliders[i].GetComponent<Rigidbody>();
//Rigidbody는 편의 기능 중 하나로 폭발의 원점을 지정해주면
//폭발물로부터 내가 스스로 얼만큼 떨어져있는지를 계산해서 내가 얼만큼 튕겨나가야할지를 계산해주는 편의기능 함수가 있음
targetRigidbody.AddExplosionForce(explosionForce, transform.position, explosionRadius);
//현재 순번의 콜라이더로부터 현재 순번의 프롭을 가져옴
Prop targetProp = colliders[i].GetComponent<Prop>();
//데미지 주기
float damage = CalculateDamage(colliders[i].transform.position);
targetProp.TakeDamage(damage);
}
//부모 자식 관계는 transform이 관리함
explosionParticle.transform.parent = null;
explosionParticle.Play();
explosionAudio.Play();
Destroy(explosionParticle.gameObject, explosionParticle.duration); //파티클 파괴
Destroy(gameObject); //자기자신 파괴
}
hp(체력) 100으로 높여서 테스트(근거리 원거리 데미지 차이 나는지)
'Unity' 카테고리의 다른 글
파워 슬라이더 (0) | 2021.07.17 |
---|---|
Package Manager에 Preview 버전이 안보인다면? (0) | 2021.07.16 |
회전 포신, 포탄 만들기 (0) | 2021.07.15 |
코루틴 (0) | 2021.07.13 |
UI / 오디오 / 최종빌드 (0) | 2021.07.13 |
댓글