본문 바로가기

IT/유니티

18. 유니티 교육 (Sebastian Lague 강의-3DShooter #5)

1. Particle Death Effect


적이 죽을때 그냥 띵! 하고 사라지면 재미있을까?

엄청 별루 일것이다.

밑의 그림처럼 파티클들이 분산하면서 없어진다면 엄청 멋있을거 같다.

첨에는 뭔가 엄청난 코딩이 필요할줄 알았는데, 그냥 파티클 시스템을 이용하면 간단히 만들수 있다.


게임 오브젝트의 파티클시스템을 선택하고 인스펙터를 확인하면 다음과 같다.



Renderer항목에서 모드는 메쉬, 메쉬는 큐브로 그리고 메터리얼은 적당한것으로 바꾼다.

그리고 이 파티클들이 방해물이나 주위환경에 반응하기 위해서 Collision항목을 선택후

World로 선택, 그리고 Collides With항목에서 바닥과 방해물만 레이어를 만든후 추가시켜준다.

만약 everything을 선택하면 코스트가 높아질 우려가 있기때문에 필요한것들하고만 충돌체크를 하게 한다.

Size Over LifeTime탭에서 시간에따라 사라지도록 설명한다.(마치 녹아 없어지듯한 효과를 줄수 있다.)

shape탭에서 콘형태의 크기를 조절한후 emission에서 burst를추가후 rate를 조절한다.

마지막으로 duration이나 start life time, start size등을 조절한다.



이렇게 만든 파티클 효과는 적이 죽을때 표현되어야 한다.

이전에 만든 livingEntity에서 takeHit함수를 virtual로 만들어서

enemy스크립트에서 다음과 같이 오버라이드 한다.


public override void TakeHit(float damage, Vector3 hitPoint, Vector3 hitDirection){


  if (damage >= health) {

Destroy (Instantiate (deathEffect.gameObject, hitPoint, 

Quaternion.FromToRotation(Vector3.forward, hitDirection)) as GameObject, deathEffect.startLifetime);

}

base.TakeHit (damage, hitPoint, hitDirection);

}



2. Weapon Effect


위에서는 적이 죽을때의 효과를 표현을 보았다.

이번에는 총을 쏠때의 효과를 표현해 보자.

우선 밑의 그림을 보자.



총이 발사될때는 아마도 위의 그림과 같이 총탄이 터지는 효과를 보여주면 훨씬 자연스럽고

멋있어 보일것이다.

세바스찬이 직접그린 4개의 그림과 아래의 소스로 구현했다.


MuzzleFlash.cs

using UnityEngine;

using System.Collections;


public class MuzzleFlash : MonoBehaviour {


//총 이펙트가 터지는 위치

public GameObject flashHolder;

//총 이펙트효과 그림

public Sprite[] flashSprites;

//이펙트 그림이 렌더러 되는 위치

public SpriteRenderer[] spriteRenderers;


public float flashTime;


void Start(){

Deactivate ();

}

//setActive를 사용하는 이유는 이 효과는 페이드인 아웃하는게 아니라 

//그냥 반짝거리고 사라지는 것이므로 

public void Activate(){

flashHolder.SetActive (true);


int flashSpriateIndex = Random.Range (0, flashSprites.Length);

for(int i = 0; i< spriteRenderers.Length; i++){

spriteRenderers[i].sprite = flashSprites[flashSpriateIndex];

}


//정해진 시간 후에 ""안의 함수를 콜한다.

Invoke ("Deactivate", flashTime);

}


void Deactivate(){

flashHolder.SetActive (false);

}

}


설명은 주석으로 대신한다.


그리고 총을 쏘면 당연히 생성되는 것은? 바로 탄피다.

많은 육군 장병들의 주적이라고 할수 있는 탄피도 만들어보자.


탄피는 총알이 나오는 위치 근처에 탄피가 나올 위치객채를 만들어 놓는다.

여기서 주의 해야 할점은 만약 탄피배출 위치가 총알이 나오는 위치보다 앞이라면 

결국 탄피가 총알과 충돌체크를 하게 되므로 총알 안나오는 버그가 생긴다.

아무튼 위치 객체를 만들고 각도도 조절해 준다. 약간 위쪽으로.


그리고 탄피는 사라져야 하므로 메터리얼을 fade로 만들어 준다.


Shell.cs

using UnityEngine;

using System.Collections;


public class Shell : MonoBehaviour {


public Rigidbody myRigidBody;

public float forceMin;

public float forceMax;


float lifeTime = 4;

float fadeTime = 2;


// Use this for initialization

void Start () {

float force = Random.Range (forceMin, forceMax);

myRigidBody.AddForce (transform.right * force);

//각도를 조정해준다. 너무 똑같은 방향으로만 배출되면 어색하니까

myRigidBody.AddTorque (Random.insideUnitSphere * force);


StartCoroutine (Fade ());

}


//탄피가 나오고 lifetime만큼 기다렸다가

//fadeTime동안 사라지는 효과를 준다.

IEnumerator Fade(){

yield return new WaitForSeconds (lifeTime);


float percent = 0;

float fadeSpeed = 1 / fadeTime;

Material mat = GetComponent<Renderer> ().material;

Color initialColor = mat.color;


while(percent < 1){

percent += Time.deltaTime * fadeSpeed;

mat.color = Color.Lerp (initialColor, Color.clear, percent);

yield return null;

}


Destroy (gameObject);

}

// Update is called once per frame

void Update () {

}

}


그리고 레이어별로 충돌체크를 하는데

Edit에 project settings안에 physics를 선택하면, 아래와 같은 그림이 나온다..

여기서 각 레이어별로 충돌체크를 편집해줄수 있다.




3. Weapon Variation

무기가 단 하나라고 아마도 재미가 없을것이다.

이제 무기를 여러개 만들어 보자.

무기의 모드는 3개, 싱글 버스트 오토


원래는 총에서는 


Gun.cs

using UnityEngine;

using System.Collections;


public class Gun : MonoBehaviour {


//총의 모드

public enum FireMode{Auto, Burst, Single};

//모드 변수

public FireMode fireMode;


//총알 나가는 구멍을 여러게 만든다.

    public Transform[] projectileSpwan;

    public Bullet projectile;

    public float msBetweenShots = 100;

    public float muzzleVelocity = 35;


public int burstCount;


public Transform shell;

public Transform shellEjection;

MuzzleFlash muzzleflash;


bool triggerReleasedSinceLastShot;

int shotsRemainingInBurst;


void Start(){

muzzleflash = GetComponent<MuzzleFlash> ();

shotsRemainingInBurst = burstCount;

}


    float nextShotTime;


    //원래는 퍼블릭이였는데, 프라이베이트로 만든다.

    void Shoot()

    {

        if (Time.time > nextShotTime)

        {

        //만약 버스트 모드라면, 남은 총알수만큼은 오토로 나간다.

if (fireMode == FireMode.Burst) {

if (shotsRemainingInBurst == 0) {

return;

}

shotsRemainingInBurst--;

//싱글은 무조건 한발만 쏘면 리턴

}else if (fireMode == FireMode.Single) {

if (!triggerReleasedSinceLastShot) {

return;

}

}


for(int i = 0; i < projectileSpwan.Length; i++){

nextShotTime = Time.time + msBetweenShots / 1000;

Bullet newProjectile = Instantiate(projectile, projectileSpwan[i].position, projectileSpwan[i].rotation) as Bullet;

newProjectile.SetSpeed(muzzleVelocity);

}

Instantiate (shell, shellEjection.position, shellEjection.rotation);

muzzleflash.Activate ();


            

        }

        

    }

        //shoot을 대신해서 장전에 관련되 함수2개로 대신한다.

public void OnTriggerHold(){

Shoot ();

triggerReleasedSinceLastShot = false;

}


public void OnTriggerRelease(){

//마우스를 떼었을때 장전이 된다.

triggerReleasedSinceLastShot = true;

shotsRemainingInBurst = burstCount;

}

}


총알이 날아갈때 단순히 총알만 날아가는것보다 그궤적도 표현해줄수 있다면 훨씬 멋지지 않을까?

이때를 이용할수 있는 컴포넌트가 Trail Renderer가 있다.

여기서 주의 점은 materials의 쉐이더를 particles/additive를 해야 한다.