지각했다...
오늘은 지각을해서 들은게 없다 그래서 설명은 나중에 듣고 일단.. 코드부터
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));
}
}