파티클 활용, 폭발, random texture,폭발력 적용(AddExplosionForce)
벽에 총알 출동시 불꽃이 튀는 효과 구현
-파티클은 표현하고자 하는 텍스처가 적용된 Mesh를 입자(Emitter)처럼 생성후 이동 및 회전시켜 효과를 표현한다.
=>입자가 많아질수록 성능에 부하를 준다.
-지금은 스파크가 튀는 방향이 항상 일정하게 생성되므로, 충돌한 지점에서 법선 벡터(Normal Vector)를 구해 해당 방향으로 스파크가 튀도록 변경한다.
https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html
드럼통 오브젝트를 추가한 후, 총에 맞으면 폭발하는 것을 구현하기 위해 barrelController 스크립트를 추가했다.
-폭발하는 순간 주변의 물체를 추출하고,드럼통에만 데미지를 적용한다.
드럼통의 레이어를 barrel로 설정한다.
Physics.OverlapSphere 함수는 폭발하는 드럼통 주위에 어떤 드럼통이 있는지 판단한다.
=> 추출하려는 반경 이내에 들어와있는 것 중에 특정 레이어만 검출한다.
-OverlapSphereNonAlloc을 쓰는 걸 권장한다. 이 함수는 결괏값을 저장할 정적 배열을 미리 선언해 사용해야 하며 실행 중에 배열의 크기를 변경할 수 없다: 메모리 Garbage가 발생하지 않도록한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BarrelController : MonoBehaviour
{
private int hitCount = 0;
private Transform tr;
[SerializeField] private GameObject expEffect; //프리팹
[SerializeField] private Texture[] textures;
[SerializeField] private float radius = 3f;
private new MeshRenderer renderer;
private Rigidbody rBody;
private void Start()
{
this.tr = GetComponent<Transform>();
this.rBody = this.GetComponent<Rigidbody>();
int idx = Random.Range(0, this.textures.Length);
this.renderer = this.gameObject.GetComponentInChildren<MeshRenderer>();
this.renderer.material.mainTexture = this.textures[idx];
}
//총알에 세발 맞으면 폭파한다
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.CompareTag("Bullet"))
{
//횟수를 증가
this.hitCount++;
Debug.LogFormat("{0}회 맞았다!", this.hitCount);
if (this.hitCount >= 3)
{
this.ExpBarrel();
}
}
}
void ExpBarrel()
{
Debug.Log("폭파");
//연출
//동적으로 폭파 이펙트 생성하기
GameObject exp = Instantiate(this.expEffect, this.transform.position, Quaternion.identity);
Destroy(exp, 0.5f);
this.rBody.mass = 1f;//무게를 가볍게
this.rBody.AddForce(Vector2.up * 1500f);//위로 힘줘서 날려버리기
this.IndirectDamage(tr.position);//간접 폭발력 전달
//3초후 드럼통 제거
Destroy(this.gameObject, 3.0f);
}
private void IndirectDamage(Vector3 pos)
{
//주변에 있는 모든 드럼통을 추출
Collider[] colls = Physics.OverlapSphere(pos, this.radius, 1 << 3);
foreach (Collider coll in colls)
{
var rb = coll.GetComponent<Rigidbody>();
rb.mass = 1f;
rb.constraints = RigidbodyConstraints.None;//freez rotation해제
rb.AddExplosionForce(1500.0f, pos, radius, 1200.0f);//폭발력을 전달
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(this.transform.position, this.radius);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
[SerializeField] GameObject sparkEffect;
private void OnCollisionEnter(Collision collision)
{
Debug.Log(collision);
if (collision.collider.CompareTag("Bullet"))
{
//충돌 지점의 법선 벡터를 구하기 위함
ContactPoint contactPoint = collision.GetContact(0);//첫 번째 충돌 지점의 정보 추출
DrawArrow.ForDebug(contactPoint.point, -1*contactPoint.normal, 5f, Color.green, ArrowType.Solid);
Quaternion rotation = Quaternion.LookRotation(-contactPoint.normal);
//충돌한 타총알의 법선 벡터를 쿼터니언 타입으로 변환
//point:위치, normal:법선
GameObject spark = Instantiate(this.sparkEffect,contactPoint.point,rotation);//스파크 파티클을 동적생성
Destroy(spark, 0.5f);// remove efffect
Destroy(collision.gameObject); //remove bullet
}
}
}
-연습 씬에서 플레이어에 가장 가까이에 있는 무기를 착용하는 코드를 작성해 보았다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OverlapPlayer : MonoBehaviour
{
[SerializeField] private float radius = 1f;
[SerializeField] private Transform weaponTrans;
private Collider[] colls = new Collider[6];
private float distance;
private float minDistance=10;
// Start is called before the first frame update
void Start()
{
int layerMask = 1 << LayerMask.NameToLayer("Gun");
int cnt = Physics.OverlapSphereNonAlloc(this.transform.position, this.radius, colls, layerMask);
Debug.Log(cnt);
foreach (Collider col in colls)
{
//Debug.Log(col.gameObject.name);
var tr = col.GetComponent<Transform>();
// Debug.Log(col.gameObject.transform.position);
this.distance = Vector3.Distance(this.transform.position, col.gameObject.transform.position);
Debug.LogFormat("{1}-distance:{0}", col.gameObject.name,distance);
if (distance < minDistance)
{
minDistance = distance;
Debug.Log(minDistance);
col.gameObject.transform.position = this.weaponTrans.position;
col.gameObject.transform.rotation = this.weaponTrans.rotation;
}
}
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(this.transform.position, this.radius);
}
}
-collider인데 콜라이더 안해놓고 멍때리지 말자..ㅋㅋ
'유니티 심화' 카테고리의 다른 글
메카님 애니메이션 제어,내비게이션-길찾기, 유한상태머신(FSM) (0) | 2023.08.23 |
---|---|
오디오, 코루틴으로 총구 효과 (0) | 2023.08.22 |
총 발사, 총알 발사 궤적 효과 만들기 - Trail Renderer (0) | 2023.08.18 |
카메라 이동 연습 2(draw gizmos, 선형 보간과 구면 선형 보간) (0) | 2023.08.18 |
Player 이동 연습2(정규화 벡터) (0) | 2023.08.18 |