[멋쟁이사자처럼 부트캠프 TIL] 멋쟁이사자처럼 유니티게임스쿨 8일차

굥지·2024년 10월 14일
0
post-thumbnail

조퇴로 인한 지금 업로드 ,, 크흠 ^_^

코루틴으로 총알 흔적 없애기

void RayCastFire()
{
    ...

    GameObject go = Instantiate(trailPrefab);
    Vector3[] pos = new Vector3[] { firingPosition.position, hitPosition };
    go.GetComponent<LineRenderer>().SetPositions(pos);

    //방법 1 Invoke()
    //방법 2
    StartCoroutine(DestroyTrail(go));        
    //방법 3
    Destroy(go, 0.1f);
}
IEnumerator DestroyTrail(GameObject obj)
	{
    yield return new WaitForSeconds(0.5f);        
    Destroy(obj);
   }
}

사용 이유

비동기 작업을 처리하면서도 게임 루프의 제어를 유지할 수 있기 때문에 사용한다.

사용 방법

IEnumerator 메소드이름()
{
yield return new WaitForSeconds(초);
}
StartCoroutine(메소드이름());

총알이 맞은 지점 나타내기

파티클이 끝난 후 어떤걸 불러올지 정할 수 있음(None, Disable, Destroy, Callback(함수 불러오기))

총알이 맞은 방향 수직으로 파티클이 튀도록

    void RayCastFire()
    {
        Camera cam = Camera.main;

        RaycastHit hit;
        Ray r = cam.ViewportPointToRay(Vector3.one / 2); //카메라 정 중앙으로 발사

        Vector3 hitPosition = r.origin + r.direction * 200; //아무곳에도 부딪히지 않았다면 카메라 방향에서 200정도 떨어져있는 곳

        if (Physics.Raycast(r, out hit, 1000)) //어딘가에 빛이 부딪혔으면 true
        { //레이 r의 정보를 가지고 1000의 최대거리 만큼 레이를 쏜다. out : 변수를 넣었을때 변수가 변할 수 있다는 것(out을 안 쓰면 오류남)
            hitPosition = hit.point; //빛이 부딪힌 부분이 총알의 종착점
            
            //총알이 부딪힌 지점의 수직으로 파티클이 튀도록
            GameObject particle = Instantiate(particlePrefab);
            particle.transform.position = hitPosition;
            particle.transform.forward = hit.point;
        }

수류탄

총과 같은 위치에 수류탄 에셋을 가져와서 두기

상속

0,0,0에 수류탄을 하나 만들어서 콜라이더를 넣어줌

얘가 projectilePrefab이 될 예정

상속되어서 인스펙터창에 다 나옴


각각 알맞은 곳에 넣어준다

using UnityEngine;

public class ProjectileWeapon : Weapon
{
    public GameObject projectilePrefab;
    public float projectileAngle = 30;
    public float projectileForce = 10;
    public float projectileTime = 5;

    protected override void Fire()
    {
        ProjectileFire();
    }
    public void ProjectileFire()
    {
        //30도 올린 각도 만들기
        Camera cam =Camera.main;

        Vector3 forward = cam.transform.forward; //카메라가 주시하는 방향 벡터
        Vector3 up = cam.transform.up; //y축 벡터

        Vector3 direction = forward + up * Mathf.Tan(projectileAngle * Mathf.Deg2Rad);
        //주시방향+(y축 * 라디안으로 치환한 발사각의 탄젠트값)

        direction.Normalize(); //벡터값 정규화
        direction *= projectileForce; //발사 방향에 발사 힘 곱해서
         
        GameObject go = Instantiate(projectilePrefab); //수류탄 인스턴스 생성
        go.transform.position = firingPosition.position; //생성한 수류탄 초기 위치 지정
        go.GetComponent<Rigidbody>().AddForce(direction, ForceMode.Impulse); //생성한 수류탄을 지정한 벡터로 투척
    }
}
public class Weapon : MonoBehaviour
{
    public void FireWeapon()
    {
        if (animator != null)
        {
            if (animator.GetCurrentAnimatorStateInfo(0).IsName("Idle"))
            {
                animator.SetTrigger("Fire");
                Fire();
            }
        }
        else
        {
            Fire();
        }

    }

    protected virtual void Fire()
    {
        RayCastFire();
    }

폭발

폭발하는 애니메이션 생성

using UnityEngine;

public class Bomb : MonoBehaviour
{
    public float time;

    private void Update()
    {
        time -= Time.deltaTime;
        if (time < 0)
        {
            GetComponent<Animator>().SetTrigger("Explode");
            Destroy(gameObject, 2f);
        }
    }
}
using UnityEngine;

public class Bomb : MonoBehaviour
{
    public float time;

    private void Update()
    {
        time -= Time.deltaTime;
        if (time < 0)
        {
            GetComponent<Animator>().SetTrigger("Explode");
            Destroy(gameObject, 2f);
        }
    }
}

수류탄 프리팹에 추가

public class ProjectileWeapon : Weapon
{
    public float projectileTime = 5;

    public void ProjectileFire()
    {  
        go.GetComponent<Bomb>().time = projectileTime;
    }
}

무기 변경

인풋 추가

Listen누르고 원하는 버튼 누르면 쉽게 가능


PlayerController 스크립트 수정

public List<Weapon> weapons;
int currentWeaponIndex;
    
    void OnChangeWeapon()
    {
        weapons[currentWeaponIndex].gameObject.SetActive(false);

        currentWeaponIndex++;
        if(currentWeaponIndex > weapons.Count-1)
        {
            currentWeaponIndex = 0;
        }
        weapons[currentWeaponIndex].gameObject.SetActive(true);
    }
public class Weapon : MonoBehaviour
{
    public GameObject trailPrefab;
    public Transform firingPosition;
    public GameObject particlePrefab;
    public TextMeshProUGUI bulletText;

    public int currentBullet = 8;
    public int totalBullet = 32;
    public int maxBulletMagazine = 8;

    Animator animator;
    void Start()
    {
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        bulletText.text = currentBullet + "/" + totalBullet;
    }
    public void FireWeapon()
    {
        if (currentBullet > 0) //현재 잔탄이 남아있을때
        {
            if (animator != null)
            {
                if (animator.GetCurrentAnimatorStateInfo(0).IsName("Idle"))
                {
                    animator.SetTrigger("Fire");
                    currentBullet--;
                    Fire();
                }
            }
            else
            {
                currentBullet--;
                Fire();
            }
        }

    }

    protected virtual void Fire()
    {
        RayCastFire();
    }

    public void ReloadWeapon()
    {
        if (totalBullet > 0) //탄약이 있으면
        {
            if (animator != null)
            {
                if (animator.GetCurrentAnimatorStateInfo(0).IsName("Idle"))
                {
                    animator.SetTrigger("Reload");
                    Reload();
                }
            }
            else
            {
                Reload();
            }

        }
    }
    void Reload()
    {
        if (totalBullet >= maxBulletMagazine - currentBullet)
            //탄약수가 (탄창 탄약 - 잔탄)보다 같거나 많으면
        {
            //꽉 채우기
            totalBullet -= maxBulletMagazine - currentBullet;
            currentBullet = maxBulletMagazine;
            //잔탄을 탄창 탄약으로 설정
        }
        else
            //탄약수가 (탄창 탄약 - 잔탄)보다 적으면
        {
            //남은 탄창 + 채울거
            currentBullet += totalBullet;
            totalBullet = 0; //탄약을 비움
        }
    }

적 Ai 만들기

적으로 지정해줘서 콜라이더 넣어주기


Nav Mesh Surface 추가후 Bake

Enemy에 Nav Mesh Agent를 추가

using UnityEngine;
using UnityEngine.AI;

public class Enemy : MonoBehaviour
{
    GameObject player;
    NavMeshAgent agent;

    void Start()
    {
        player = GameObject.FindWithTag("Player");
        agent = GetComponent<NavMeshAgent>(); 
    }

    void Update()
    {
        agent.destination = player.transform.position;
    }
}

내가 가있던 자리로 쫓기

using UnityEngine;
using UnityEngine.AI;

public class Enemy : MonoBehaviour
{
    GameObject player;
    NavMeshAgent agent;

    void Start()
    {
        player = GameObject.FindWithTag("Player");
        agent = GetComponent<NavMeshAgent>(); 
    }

    void Update()
    {
        //destination까지 남은 거리(흔적쫓기)
        if (agent.remainingDistance<1f)
        {
            agent.destination = player.transform.position;
        }
    }
}

0개의 댓글

관련 채용 정보