using UnityEngine;
public class BarrelCtrl : MonoBehaviour
{
private int hitCount = 0;
private Transform trans;
private Rigidbody rb;
public GameObject explosionPrefab;
public Material[] materials;
private new MeshRenderer renderer;
//폭발 반경
public float radius = 10f;
void Start()
{
this.trans = this.GetComponent<Transform>();
this.rb = this.GetComponent<Rigidbody>();
//자식에 있는 랜더러 컴포넌트를 찾아옴
this.renderer = this.GetComponentInChildren<MeshRenderer>();
//난수 발생
int index = Random.Range(0, this.materials.Length);
//텍스쳐 변경
this.renderer.material = materials[index];
}
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.CompareTag("Bullet"))
{
if (++hitCount == 3)
{
ExplodeBarrel();
}
}
}
private void ExplodeBarrel()
{
//폭파 이펙트를 생성
GameObject exp = Instantiate(explosionPrefab, this.trans.position, Quaternion.identity);
//이펙트 5초 있다가 제거
Destroy(exp, 1f);
//힘을 위로 가함
//this.rb.mass = 1.0f; //질량을 줄여주고
//this.rb.AddForce(Vector3.up * 1500); //위로 힘을 가한다
//간접 폭발력 전달
IndirectDamage(this.trans.position);
//3초후 드럼통 제거
Destroy(this.gameObject, 3);
}
private void IndirectDamage(Vector3 pos)
{
//주변에 있는 드럼통들을 모두 추출
Collider[] colls = Physics.OverlapSphere(pos, this.radius, 1 << 3);
foreach (var coll in colls)
{
var rb = coll.GetComponent<Rigidbody>();
rb.mass = 1.0f;
rb.constraints = RigidbodyConstraints.None;
//횡 폭발력, 폭발 원점, 폭발 범위, 종 폭발력
rb.AddExplosionForce(1500, pos, radius, 1200);
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(this.transform.position, this.radius);
}
}
BarrelCtrl.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
public GameObject sparkEffectPrefab;
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.CompareTag("Bullet"))
{
//첫번째 충돌 지점의 정보 추출
ContactPoint contactPoint = collision.contacts[0];
DrawArrow.ForDebug(contactPoint.point, -contactPoint.normal, 10, Color.red);
//충돌한 총알의 법선 벡터를 쿼터니언으로 변환
Quaternion rot = Quaternion.LookRotation(-contactPoint.normal);
GameObject spark = Instantiate(this.sparkEffectPrefab, contactPoint.point, rot);
Destroy(spark, 0.5f);
Destroy(collision.gameObject);
}
}
}
RemoveBullet.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowCam : MonoBehaviour
{
public Transform targetTr;
private Transform camTr;
//대상으로 부터 떨어질 거리
[Range(2.0f, 20.0f)]
public float distance = 10.0f;
//Y축으로 이동할 높이
[Range(0.0f, 10.0f)]
public float height = 2.0f;
void Start()
{
this.camTr = GetComponent<Transform>(); //Transform 객체 캐싱
}
private void LateUpdate()
{
//추적할 대상의 뒤쪽 distance만큼 이동
//높이를 height만큼 이동
this.camTr.position = this.targetTr.position +
(-targetTr.forward * distance) +
(Vector3.up * height);
//Camera를 피벗 좌표를 향해 회전
this.camTr.LookAt(this.targetTr.position);
}
}
FollowCam.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCtrl : MonoBehaviour
{
private Transform tr;
public float moveSpeed = 10.0f;
public float turnSpeed = 80.0f;
private Animation anim;
private void Awake()
{
//제일먼저 호출되는 함수
//스크립트가 비활성화돼 있어도 호출되는 함수
}
private void OnEnable()
{
//두번째로 호출되는 함수
//스크립트가 활성화 될때마다 호출되는 함수
}
void Start()
{
// 세번째로 호출되는 함수
//Update함수가 호출되기 전에 호출되는 함수
//코루틴으로 호출될수 있는 함수
//예)
//IEnumerator Start(){}
tr = GetComponent<Transform>();
this.anim = GetComponent<Animation>();
//이름으로 실행 하거나
this.anim.Play("Idle");
//이름으로 가져와서 플레이 하거나
//this.anim.clip = this.anim.GetClip("Idle");
//this.anim.Play();
}
private void FixedUpdate()
{
//일정간격으로 호출되는 함수 (기본값은 0.02초)
//물리엔진의 계산 주기와 일치
}
void Update()
{
//프레임마다 호출되는 함수
//호출 간격이 불규칙하다
//화면의 렌더링 주기와 일치 함
float h = Input.GetAxis("Horizontal"); //-1.0 ... 0.0 ... 1.0
float v = Input.GetAxis("Vertical"); //-1.0 ... 0.0 ... 1.0
float r = Input.GetAxis("Mouse X");
//Debug.Log("h=" + h);
//Debug.Log("v=" + v);
Debug.Log(r);
//매 프레임마다 10유닛씩 이동
//this.tr.Translate(Vector3.forward * 1);
//매 초마다 1유닛씩 이동
//프레임 레이트가 서로다른 기기에서도 개발자가 지정한 일정한 속도로 이동하기 위함
//전후좌우 이동방향 벡터 계산
Vector3 moveDir = (Vector3.forward * v) + (Vector3.right * h);
//방향 * 속도 * 시간
this.tr.Translate(moveDir.normalized * moveSpeed * Time.deltaTime);
//Vector3.up 축으로 turnSpeed만큼 속도로 회전
this.tr.Rotate(Vector3.up * r * this.turnSpeed);
//캐릭터 애니메이션 설정
PlayerAnim(h, v);
}
private void LateUpdate()
{
//Update함수가 종료된후 호출 되는 함수
}
private void PlayerAnim(float h, float v)
{
//키보드 입력값을 기준으로 동작할 애니메이션 실행
if (v >= 0.1f)
{
//0.25f초간 이전 애니메이션과 실행할 애니메이션을 보간
this.anim.CrossFade("RunF", 0.25f); //전진 애니메이션 실행
}
else if (v <= -0.1f)
{
this.anim.CrossFade("RunB", 0.25f);//후진
}
else if (h >= 0.1f)
{
this.anim.CrossFade("RunR", 0.25f);//오른쪽
}
else if (h <= -0.1f)
{
this.anim.CrossFade("RunL", 0.25f);//왼쪽
}
else
{
this.anim.CrossFade("Idle", 0.25f);//기본
}
}
}
PlayerCtrl.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FireCtrl : MonoBehaviour
{
public GameObject bulletPrefab;
public Transform firePoint;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
this.Fire();
}
}
private void Fire()
{
Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
}
}
FireCtrl.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletCtrl : MonoBehaviour
{
public float damage = 20.0f;
public float force = 1500f;
private Rigidbody rb;
void Start()
{
this.rb = this.GetComponent<Rigidbody>();
this.rb.AddForce(this.transform.forward * force);
}
}
BulletCtrl.cs
++++
총구에 화염효과 (Muzzle Flash)와 총 쏘는 소리 삽입하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FireCtrl : MonoBehaviour
{
public GameObject bulletPrefab;
public Transform firePoint;
public AudioClip fireSfx;
private AudioSource audioSource;
private MeshRenderer muzzleFlash;
private Coroutine muzzleFlashCoroutine;
private void Start()
{
audioSource = GetComponent<AudioSource>();
muzzleFlash = this.firePoint.GetComponentInChildren<MeshRenderer>();
muzzleFlash.enabled = false;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
this.Fire();
}
}
private void Fire()
{
Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
audioSource.PlayOneShot(fireSfx, 1f);
if (muzzleFlashCoroutine != null) StopCoroutine(muzzleFlashCoroutine);
this.muzzleFlashCoroutine = StartCoroutine(this.ShowMuzzleFlash());
}
IEnumerator ShowMuzzleFlash()
{
Vector2 offset = new Vector2(Random.Range(0, 2), Random.Range(0, 2)) * 0.5f;
muzzleFlash.material.mainTextureOffset = offset;
float angle = Random.Range(0, 360);
muzzleFlash.transform.localRotation = Quaternion.Euler(0, 0, angle);
float scale = Random.Range(1, 2);
muzzleFlash.transform.localScale = Vector3.one * scale;
muzzleFlash.enabled = true; //보여주기
yield return new WaitForSeconds(0.2f); //0.2초후
muzzleFlash.enabled = false; //안보여주기
}
}