화살 파티클 생성

발리스타의 머리 부분에 파티클을 생성하고 Render Mode는 Mesh로 Meshes에서 화살Mesh Filter를 선택하고 Material에서 Palette를 선택한다.

RenderAlignment를 Velocity로 바꾸어 메시가 이동하는 방향으로 보이게 만든다.

Renderer 설정

Shape는 끄고 Emission의 Rate over Time을 1로 만들고

Shape, Emssion

Type을 World로 바꿔주고

Collision을 켜주고 Lifetime Loss를 1로 만든다 - 이것은 충돌시 Lifetime과 관련있다.(0~1 / 1로갈수록 바로 사라짐)

Radius Scale, Visualize Bounds 까지 바꿔준다.

Collision

Particle System의 Position과 Lifetime Speed Size까지 조절해준다.

나머지 조절

 

적 콜라이더

적의 Collider도 붙인다.

Box Collider

 

적 피격

적 피격시 체력을 깎는 로직이다.

적 피격
체력 다 감소시 파괴

타워 설치하기

WayPoint에서 개체를 이미 마우스 입력으로 추적하고 있기 때문에 WayPoint에서 타워 설치를 작성 한다.

타워 설치
실행

그러나 한 타일에 타워 여러 개가 설치가 가능해서 이것을 바꿔줘야한다.

한 타일에 타워 2개

isPlaceable을 false로 바꿔줘서 타워를 지을 수 없게 한다.

isPlaceable = false
실행화면

 

적 추적하기

타겟의 transform을 FindObjectOfType<EnemyMover>으로 받아오고(EnemyMover가 우리의 타겟의 개체니까)

weapon

타겟 추적하기
설치하면 잘 추적한다.

프리펩 세팅

OnMousexxx 함수는 박스 콜라이더를 내포한 개체에서만 실행되기 때문에 

마우스 입력을 탐지하기 위한 Collider를 Tile 프리펩에 추가해준다.

* 해당 개체에 콜라이더가 없는 CoordinateLabel(자식 오브젝트 Text의 스크립트)에서 OnMouseButton에서 사용한다면 문제가 생길 것이다.

Collider 추가하기

OnMouseOver로 해당 개체 위에 마우스를 올려놓았을 때 이름을 출력했다.

OnMouseOver()
출력

마우스를 클릭했을 시 이름 출력

마우스 클릭시
클릭 시 출력

설치가 가능한 타일만 선택이 가능하도록 만들기 위해 SerializeFile bool 변수를 선언해서 isPlaceable이 true일 때만 출력하게 하고

isPlaceable

가장 상위 개체인 Tile 프리펩의 isPlaceable을 체크하면 자손들도 같이 체크가 되니까 Tile의 자식에게 체크 해제를 해주면 Tile 자손들이 다 체크 해제가 된다.

체크 / 체크 해제

Road 타일을 마우스로 선택해도 체크가 안 된다.

결과

 

적 메시 바꾸기 

메시를 바꾸고 Enemy 스크립트만 적용해준다.

적 메시 바꾸기
잘 움직인다.

 

Lerp를 사용하여 적 움직임 부드럽게 하기

Vetor3.Lerp(시작위치, 목표위치, 0~1) // 0에서 1은 시작위치에서 목표위치로의 비율이다.

부드럽게 이동하기

Range 속성으로 Speed를 설정하여 인스펙터에서 조절이 가능하도록 했다.

Range

 

프리펩 변형(Prefab Variant)

프리펩에 우클릭 - Create - Prefab Variant를 누르면 새 프리펩이 생성된다.

Prefab Variant

Prefab Variant는 저렇게 빗금이 쳐져있는 프리펩 모양으로 생성된다.

Prefab Variant는 프리펩의 자녀로 생각하면 된다. 프리펩의 모든 수정사항은 특정 매개변수를 오버라이드하지 않는 이상 Variant에 반영된다.

Variant 생성

이전에 만든 Prefab Variant에서 Mesh Filter를 바꿔준다. Mesh Filter는 mesh의 틀이라고 생각된다.

Mesh Filter

변경한 Mesh Filter를 제외한 다른 것들이 Tile에서 온 것을 알 수 있다.

Tile의 자식 개념

Tile 프리펩을 수정하면 Tile 프리펩의 Variant인 Tile_RoadStraight도 변경사항이 적용되게 된다.(둘은 연결되어 있음)

Tile_RoadStraight에 적용

위의 과정으로 모서리도 만들어줬다.

하나 더 만들기

길의 방향을 나타내기 위해 타일 자체를 회전하면 Text도 같이 회전한다.

Tile 회전하기

이를 막기위해 Tile Mesh만 회전하는 방법이 있지만 그 때마다 회전하기는 불편하다.

Tile Mesh 회전

그래서 Prefab Variant의 Prefab Variant를 만들 수 있다는 것을 이용해 각 방향의 프리펩을 만들어주면 된다. (위 방법을 방향마다 한 번 씩만 적용해주면 된다.)

그리고 아까와 같이 Prefab Variant를 수정하면 Prefab Variant의 Variant도 수정된다.

프리펩 Variant의 Variant

이 상황에서 Tile 프리펩을 변경해도 Prefab Variant와 Prefab Variant의 Variant는 변경되지 않는데

?

Variant의 Scale이 기존 Tile 프리펩에 Override하고 있기 때문이다. Revert하면 Tile 프리펩의 Scale로 돌아간다.

Override

Revert 한 후 다시 Tile Scale을 바꾸면

Revert

Tile 프리펩부터 Tile의 Variant 프리펩, Variant의 Variant 프리펩까지 적용이 되는 걸 볼 수 있다.

적용이 잘 된다.

누구의 Variant인지 헷갈릴 때 Variant의 Open에 커서를 올리면 해당 정보가 나와있다. 그리고 누르면 그 Variant의 원본 프리펩으로 가게 된다.

누구야?

이렇게 이동하면 좌측 상단에 프리펩 이동 흐름이 나와있다.

Tile Straight 90 -> Tile Straight -> Tile

 

실습

타일들을 정리해주고 Path를 순서대로 맞춰서 한번에 Enemy의 Path List에 넣어준다.

실습

실행

잘 이동하는 걸 볼 수 있다.

실행

 

외부 에셋

외부 에셋 오류

외부 에셋이 마젠타 색일 때 Material을 못 찾았을 때가 많다. 여기선 Magica Voxel이라는 프로그램에서 생성해서 Material을 Palette로 만들어주면 된다.

마젠타 색
Material 추가

 

중첩 프리펩

프리펩 안에 프리펩이 들어가 있는 것을 중첩 프리펩이라고 한다.

이후 Grass Prefab의 프리펩 모드로 들어가 스케일을 변경하고 나와보면

Grass Prefab

타일 프리펩도 변경되어 있는 걸 볼 수 있다. 이 상황에서 자식 프리펩을 사용하는 모든 씬창의 프리펩을 수정할 필요가 없다.

타일 프리펩도 변경됨

이 프로젝트에서는 모든 타일의 프리펩 베리언트 몇 개를 만들고 싶기 때문에 위계와 타일 개체가 살짝 다를 필요가 있다.

GrassMesh를 Grass 프리펩에 영향을 주지 않고 Tile 자식으로 만들고 싶으니 Prefab을 Unpack한다.

Unpack Prefab

이후에 GrassMesh를 Mesh로 수정했다.

Grass Mesh이름 -> Mesh

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 레엄 러쉬' 카테고리의 다른 글

적 움직임 매끄럽게 하기  (0) 2022.09.02
프리펩 변형(Prefab Variant)  (0) 2022.09.02
코루틴  (0) 2022.09.02
리스트와 적 웨이포인트  (0) 2022.09.02
좌표계  (0) 2022.09.01

InvokeRepeating()

코루틴을 사용하기 전에 '프로젝트 부스트'에서 Invoke라는 함수를 사용했었다. (지연함수) 그 함수를 반복하는 게 InvokeRepeating()이다.

처음엔 Start에서 불렸다가 그 다음부터는 InvokeRepeating에서 불려서 8개가 출력된 것이다. (Collapse 설정일 때)

InvokeRepeating

하지만 이렇게 동시에 좌표가 출력되는 것을 원한 게 아니라 좌표당 일정 시간 간격으로 출력되길 원한다. => 이 때 사용할 수 있는 게 코루틴이다.

InvokeRepeating 출력

 

코루틴(Coroutine)

Invoke는 함수를 호출할 때 문자열로 참조했지만 코루틴은 메서드 명으로 호출한다.

코루틴

실행하면 1초마다 출력이 되는 것을 볼 수 있다. 순서가 Start here -> 리스트 1번째 좌표 -> finishing start -> 2 -> 3 -> 4순이다.

코루틴 순서

이렇게 좌표 순서대로 이동할 수 있다.

웨이포인트로 위치 이동하기
리스트대로 이동

리스트와 배열

배열

- 사이즈 : 고정

- 성능 : 빠름

- 사용성 : 쉬움

- 유연성 : 낮음 

리스트

- 사이즈 : 유동적

- 성능 : 크기에 따라 다름

- 사용성 : 쉬움

- 유연성 : 큼

 

적 생성

빈 오브젝트를 생성하고 자식으로 Cylinder를 넣어 Cylinder에서 타일의 위로 오게 y축을 맞추고 부모 오브젝트에서 이동을 시킨다.

부모 오브젝트인 Enemy도 이전에 Grid Snapping 설정을 해놓았기 때문에 10unit 씩 움직이는 걸 볼 수 있다. 

적 생성

타일 프리펩의 Material을 변경할 때 오류 메시지가 뜨는데 프리펩의 이름과 지금 편집모드에서의 이름이 달라서 그렇다. 지금 상황에 별 영향을 주지 않으므로 Use Old Name을 선택했다.(이 메시지는 이후에 타일 프리펩을 수정할 때마다 뜰 것이다.)

* 이전에 TextMeshPro 오브젝트에 들어있는 CoordinateLabeler의 좌표에 따른 이름 동기화로 이름이 바뀌어져 있는 상황이다.

타일에 색 입히기

적에도 색을 입혔다.

적에 색 입히기

 

적 웨이포인트

문자열 참조 문제가 있는 태그로 체크하는 대신 WayPoint라는 타입으로 리스트에 담고 체크하는 방식이다.

리스트
웨이포인트

 

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 레엄 러쉬' 카테고리의 다른 글

외부 에셋과 중첩 프리펩  (0) 2022.09.02
코루틴  (0) 2022.09.02
좌표계  (0) 2022.09.01
텍스트 레이블  (0) 2022.09.01
그리드 스내핑  (0) 2022.09.01

좌표계 만들기

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

// 편집모드와 플레이모드에서 둘다 실행됨
// 실수로 수정하는 일이 없도록 유의 해야함
[ExecuteAlways]
public class CoordinateLabeler : MonoBehaviour
{
    private TextMeshPro label;
    private Vector2Int coordinates = new Vector2Int();

    private void Awake()
    {
        label = GetComponent<TextMeshPro>();
    }

    void Update()
    {
        // 플레이 중이 아니므로
        // 편집 모드에서만 실행될 것임
        if (!Application.isPlaying)
        {
            DisPlayCoordinates();
        }
    }

    private void DisPlayCoordinates()
    {   // parent를 가져오는 이유는 TextMeshPro가 Tile의 자식 오브젝트로 있어서 그렇다.
        // * 실제 위치 좌표는 Tile이 가지고 있음
        coordinates.x = Mathf.RoundToInt(transform.parent.position.x);
        coordinates.y = Mathf.RoundToInt(transform.parent.position.z); // 3D환경이니까 값이 Position.z이다.
        label.text = $"({coordinates.x}, {coordinates.y})";
    }
}

씬에서 이동하면 좌표가 뜬다.

좌표계

그러나 플레이 모드에서는 좌표가 망가진다.

=> 스크립트가 플레이 모드에서만 실행되기 때문이다.

초기화 됐음

해결하려면 Update 전에 Awake에서 DisPlayCoordinates 호출로 초기화를 한 번 해준다. 

Awake()

이후 DisPlayCoordinates()의 안을 아래와 같이 수정한다. => text 내용을 1 단위로 맞추기 위함

UnityEditior.EditorSnapSettings.move.~

그러고나면 플레이 모드에서도 실행이 잘 된다!

플레이 모드

이후에 타일 이름도 좌표 값으로 변경하기 위해 코드를 작성한다.

타일 이름 변경하기

타일 이름이 잘 바뀌었고 편집 모드에서 움직이면 타일 텍스트와 이름도 바뀐다.

편집모드

플레이 모드에선 영향을 주지 않는다.

플레이모드 2

 

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 레엄 러쉬' 카테고리의 다른 글

코루틴  (0) 2022.09.02
리스트와 적 웨이포인트  (0) 2022.09.02
텍스트 레이블  (0) 2022.09.01
그리드 스내핑  (0) 2022.09.01
레엄 러쉬 게임 디자인  (0) 2022.09.01

Text Mesh Pro

TextMeshPro는 3D 오브젝트로도 있다.

3D 오브젝트인 TextMeshPro

다른 UI 요소와는 다르게 월드의 타 개체에 의해 불투명해질 수 있다.

불투명해진 TextMeshPro

TextMeshPro의 크기를 큐브와 같게 맞췄고 회전을 x축으로 90도를 줬으며 같은 레벨의 Cube Mesh의 y축 좌표를 -4.5만큼 이동했다.

* 폰트가 이상하게 보이는 이유는 Z-fighting 또는 Z-buffer fighting이라 불리는 것 때문인데 지금 상황에서는 큐브의 텍스트와 상단면이 정확히 똑같은 공간을 차지하려해서 발생한다.

레이블 보이게 하기

해결 방안 1.

한 오브젝트의 위치를 살짝 조정하기

해결방안 1.

해결방안 2.

TextMeshPro의 쉐이더 변경 -> TextMeshPro - Distance Field Overlay

Distance Field Overlay

이렇게하면 y축이 몇이든 Overlay된다.

y축을 낮춰도 보인다.

이후 설정한 타일을 프리펩화하여 템플릿으로 사용한다.

프리펩화

 

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 레엄 러쉬' 카테고리의 다른 글

코루틴  (0) 2022.09.02
리스트와 적 웨이포인트  (0) 2022.09.02
좌표계  (0) 2022.09.01
그리드 스내핑  (0) 2022.09.01
레엄 러쉬 게임 디자인  (0) 2022.09.01

+ Recent posts