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;    //안보여주기 
    }
}

+ Recent posts