[24.02.19]Unity - Tank

손지·2024년 2월 19일
0

Unity

목록 보기
11/44

지각했다...

오늘은 지각을해서 들은게 없다 그래서 설명은 나중에 듣고 일단.. 코드부터

TankController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TankController : MonoBehaviour
{
    //TankMove에는 움직이는 기능만 만들어 두고 TankController에서 호출해서 움직이는 방식
    [SerializeField] private TankMove tankMove = null;

    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
            tankMove.MoveForward();
        if (Input.GetKey(KeyCode.S))
            tankMove.MoveBack();

        if (Input.GetKey(KeyCode.A))
            tankMove.TurnLeft();
        if (Input.GetKey(KeyCode.D))
            tankMove.TurnRight();
    }
}

Tankmove.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TankMove : MonoBehaviour
{
    [SerializeField, Range(10f, 30f)] private float moveSpeed = 30f;
    [SerializeField, Range(100f, 200f)] private float turnSpeed = 200f;

    public void MoveForward() {
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime); // transform에 있는 회전행렬을 건드는 것
    }

    public void MoveBack() {
        transform.position = transform.position + ((transform.forward * -1f) * turnSpeed * Time.deltaTime);
    }

    // X : Pitch, Y : Yaw, Z : Roll
    public void TurnLeft() {
        transform.Rotate(Vector3.up, -1f * turnSpeed * Time.deltaTime); // Rotate(증분값)
    }

    public void TurnRight() {
        transform.rotation = transform.rotation * Quaternion.Euler(0f, turnSpeed * Time.deltaTime, 0f);
    }
}

TankTurret.cs

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;
using UnityEngine;

public class TankTurret : MonoBehaviour
{

    public void TurnWithTarget(Vector3 _target){
        StopAllCoroutines();
         
        StartCoroutine(TurnCoroutine(_target));
    }
    //Co - Op
    //코루틴(Coroutine)
    //Task Manager
    private IEnumerator TurnCoroutine(Vector3 _target) {
        Vector3 startAngle = transform.rotation.eulerAngles;
        Vector3 endAngle;


        Quaternion start = transform.rotation;

        _target.y = transform.position.y;
        Vector3 dir = (_target - transform.position);
        dir.Normalize();

        Quaternion end = Quaternion.LookRotation(dir);

        float t = 0f;
        while( t < 1f)
        {
            
            //Lerp : Linear Interpolation ( 선형 보간 )
            transform.rotation = Quaternion.Lerp(start, end, t);

            t += Time.deltaTime;
            Debug.DrawLine(transform.position,_target,Color.yellow);
            yield return null;
        }
        transform.rotation = end;
    }
}


여기까지 만든사람 : https://odds-and-ends-box.tistory.com/
Utillity.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Transformtion Metrix
// Liner Transformation
// Liner 
public class Utillity
{
    public static Mesh CreateMeshQuad(string _name = "Deafult")
    {
        Mesh mesh = new Mesh();
        mesh.name = _name;
        //0--1
        //l  l
        //2--3
        //Vertex / Vertex Buffer
        Vector3[] vertices = new Vector3[4]
        {
            new Vector3(-0.5f, 0.5f, 0f),
            new Vector3(.5f, .5f, 0f),
            new Vector3(-0.5f , -0.5f, 0f),
            new Vector3(0.5f, -0.5f, 0f)
        };

        mesh.vertices = vertices;
        //Index / Index Buffer
        //CW(시계방향 , 앞면) / CCW(반 시계방향, 뒷면)
        //Backface Culling(은면 제거)
        int[] indices = new int[6]
        {
            0,1,2,
            1,3,2
        };
        mesh.triangles = indices;

        //UV Coordinate
        // Texture / Texture Mapping
        Vector2[] uvs = new Vector2[4]
        {
            new Vector2(0f, 1f),  //LU
            new Vector2(1f, 1f),  //RU
            new Vector2(0f, 0f),  //LD
            new Vector2(1f, 0f)   //RD
        };
        mesh.uv = uvs;

        //Normal Vector
        Vector3[] normals = new Vector3[4]
        {
            new Vector3(0f, 0f, -1f),
            new Vector3(0f, 0f,-1f),
            new Vector3(0f, 0f, -1f),
            new Vector3(0f, 0f, -1f)
        };
        mesh.normals = normals;

        //마젠타가 보이면 쉐이더가 깨진거임
        return mesh;
    }

   
    public static bool Picking(ref Vector3 _point)
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit)){
            _point = hit.point;

            return true;
        }

        return false;
    }
}

그리고 대포알을 만들기위해서

캐논볼 프리팹을 만들고 캡슐을 넣어서 x에 90도로 만듭니다.

그리고 콜라이더를 없앱니다

그리고 총구앞에 빈 오브젝트를 만들고 Y 위치를 1.5위치로 보냅니다.

스크립트

그리고 vfx 효과를 위한 프리팹을 하나 더 만들고

이와같이 설정합니다.

총합 :

FXExplosion.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FXExplosion : MonoBehaviour
{
    private float duration = 0.5f;
    private float speed = 30f;
    
    private void Start()
    {
        duration = Random.Range(0.5f, 1f);
        Destroy(gameObject, duration);
    }

    private void Update() {
        transform.localScale += Vector3.one * speed * Time.deltaTime;
    }
}

TankCannonball.cs

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
// 커플링
// 의존
// 위에꺼가 되면안됨
public class TankCannonBall : MonoBehaviour
{
    public delegate void OnDestoryDelegate(Vector3 _pos);
    private OnDestoryDelegate onDestroyCallback = null;
    public OnDestoryDelegate OnDestroyCallback
    {
        set { onDestroyCallback = value; }
    }
    private float moveSpeed = 40f;
    [SerializeField] private GameObject fxExplosionPrefab = null;
    private void Awake()
    {
        //fxExplosionPrefab = Resources.Load("Prefabs\\P_FX_Explosion") as GameObject;
    }
    private void Update()
    {
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
        if (Input.GetKeyDown(KeyCode.P))
        {
            // 게임 오브젝트에서 해당(TankCannonBall) 스크립트가 삭제
            Destroy(this);
        }
    }
    private void OnTriggerEnter(Collider _collider)
    {
        if (_collider.CompareTag("Wall"))
        {
            // 해당 게임 오브젝트 삭제
            Destroy(gameObject);
        }
    }
    private void OnDestroy()
    {
        //Instantiate(fxExplosionPrefab, transform.position, Quaternion.identity);
        onDestroyCallback?.Invoke(transform.position);
    }
}

TankTurret.cs

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;
using UnityEngine;

public class TankTurret : MonoBehaviour
{
    [SerializeField] private Transform spawnPointTr = null;

    [SerializeField] private GameObject cannonBallPrefab = null;

    private void Awake()
    {
        cannonBallPrefab = Resources.Load("Prefabs\\P_CannonBall") as GameObject;
    }
    public void TurnWithTarget(Vector3 _target){
        StopAllCoroutines();
         
        StartCoroutine(TurnCoroutine(_target));
    }
    //Co - Op
    //코루틴(Coroutine)
    //Task Manager
    private IEnumerator TurnCoroutine(Vector3 _target) {
        Vector3 startAngle = transform.rotation.eulerAngles;
        Vector3 endAngle;


        Quaternion start = transform.rotation;

        _target.y = transform.position.y;
        Vector3 dir = (_target - transform.position);
        dir.Normalize();

        Quaternion end = Quaternion.LookRotation(dir);

        float t = 0f;
        while( t < 1f)
        {
            
            //Lerp : Linear Interpolation( 선형 보간 )
            transform.rotation = Quaternion.Lerp(start, end, t);

            t += Time.deltaTime;
            Debug.DrawLine(transform.position,_target,Color.yellow);
            yield return null;
        }
        transform.rotation = end;
    }
    

    public void Fire(TankCannonBall.OnDestoryDelegate _onDestroyCallback)
    { 
        GameObject go = Instantiate(cannonBallPrefab, spawnPointTr.position, spawnPointTr.rotation);
        TankCannonBall cannonBall = go.GetComponent<TankCannonBall>();
        cannonBall.OnDestroyCallback = _onDestroyCallback;
    }
}

TankMove.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TankMove : MonoBehaviour
{
    [SerializeField, Range(10f, 30f)] private float moveSpeed = 30f;
    [SerializeField, Range(100f, 200f)] private float turnSpeed = 200f;

    public void TankForward() {
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime); // transform에 있는 회전행렬을 건드는 것
    }

    public void TankBack() {
        transform.position = transform.position + ((transform.forward * -1f) * moveSpeed * Time.deltaTime);
    }

    // X : Pitch, Y : Yaw, Z : Roll
    public void TurnLeft() {
        transform.Rotate(Vector3.up, -1f * turnSpeed * Time.deltaTime); // Rotate(증분값)
    }

    public void TurnRight() {
        transform.rotation = transform.rotation * Quaternion.Euler(0f, turnSpeed * Time.deltaTime, 0f);
    }
}

TankController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankController : MonoBehaviour
{
    [SerializeField] private TankMove tankMove = null;
    private Vector3 point = Vector3.zero;
    [SerializeField] private TankTurret tankTurret = null;
    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            tankMove.TankForward();
        }
        if (Input.GetKey(KeyCode.S))
        {
            tankMove.TankBack();
        }
        if (Input.GetKey(KeyCode.D))
        {
            tankMove.TurnRight();
        }
        if (Input.GetKey(KeyCode.A))
        {
            tankMove.TurnLeft();
        }
        if (Input.GetMouseButtonDown(0))
        {
            if (Utility.Picking(ref point))
            {
                tankTurret.TurnWithTarget(point);
            }
        }
        if (Input.GetMouseButtonDown(1))
        {
            tankTurret.Fire(OnDestoroyCannonBall);
        }
    }
    private void OnDestoroyCannonBall(Vector3 _pos)
    {
        // 소리
        // 포탄 갯수
        // 파괴될때마다 캐논볼 Prefab을 불러오기때문에 매우 안좋은코드임 위에서 불러서 1번만 불러오는게 좋음
        Instantiate(Resources.Load("Prefabs\\P_FX_Explosion"), _pos, Quaternion.identity);
    }
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawLine(point, point + (Vector3.up * 3f));
        Gizmos.color = Color.white;
        Gizmos.DrawLine(point, point + (Vector3.right * 3f));
    }
}
profile
게임 개발자가 될사람

0개의 댓글

관련 채용 정보