게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발 4주차
1.C# Linq 라이브러리의 OrderBy()의 정렬 알고리즘
OrderBy는 병합정렬 기반의 알고리즘을 사용하였으며,
.NET에서 OrderBy는 내부적으로 TimSort알고리즘을 사용중이다.
OrderBy는 매개변수 데이터 기준으로 오름차순 정렬을 한다.
내림 차순을 원하면 OrderByDescending을 호출해야한다.
p.s 키워드
*병합정렬(MergeSort) :
1.안전정렬에 속하며 분할 정복 알고리즘의 하나 이다.
//따로 병합정렬 게시글을 만들어 정리 할것
*.NET :
.NET은 다양한 유형의 애플리케이션을 빌드하기 위한 무료 크로스 플랫폼 오픈 소스 개발자 플랫폼입니다. 이는 여러 언어로 작성된 프로그램을 실행할 수 있으며, 그 중 가장 인기 있는 언어는 C#입니다. 이는 많은 대규모 앱 프로덕션에서 사용되는 고성능 런타임에 의존합니다. - MicroSoft 메뉴얼 참조
.NET 은 다양한 언어(C#,F#,VB NET등등)을 이용해 프로그램을 개발하는 프레임 워크로 이 프레임 워크를 사용하여 다양한 플랫폼(윈도우,리눅스,macOS,모바일 등등)에서 실행 가능케해주는 플랫폼과 언어 간의 호환성을 제공하는 프레임 워크라고 생각하면 된다.
간단한 동작 과정
1.프로그램 코드가 C#, VB.NET 같은 고급 프로그래밍 언어로 작성.
2.위에 작성한 코드를 컴파일
3.NET 컴파일러가 이 코드를 CIL( Common Intermediate Language )이라는 중간언어로 변환합니다.
4.그리고 이 CIL 코드는 각 플랫폼에 맞는 .NET 런타임에 의해 실행됩니다.
(사진출처 - 위키피디아 백과사전)
*TimSort 알고리즘 :
2002년 소프트웨어 엔지니어 Tim Peters에 의하여 Tim Sort 알고리즘이 등장했다.
이 알고리즘은 삽입 정렬과 병합정렬을 결합하여 만든 정렬이다.
현재 2.3 이후 버전의 Python, Java SE 7, Android, Google chrome (V8), 그리고 swift까지 많은 프로그래밍 언어에서 표준 정렬 알고리즘으로 채택되어 사용
//따로 정렬 게시글을 만들어 정리 할것
2.랜덤으로 원소를 섞기 알고리즘 ( Fisher-Yates shuffle)
해당 강의에서 카드를 섞어서 배열해야되기 때문에 OrderBy()메서드에 x=>Random.Range() 를 매개변수로 넣어서 간단한 셔플 기능을 넣었었다. 하지만 위의 방법은 간단하게 셔플기능을 만드는것에 특화되 있지 효율적으로 볼수가 없다.
이 기능은 Random.Range로 숫자 난수를 뽑아오기에 O(n) 시간이 걸리고
이제 정렬을 위해 OrderBy가 동작하면 O(n log n)이기에 시간면에서 비효율적이다.
하지만 Fisher-Yates shuffle 알고리즘의 시간복잡도는 O(n)이기 최적화면에서 매우 훌륭하다.
다음 프로젝트때 셔플기능을 사용할때 이 알고리즘을 사용해보자
3. m x n 배열에 오브젝트를 배치하는 알고리즘
int[] arr = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
arr = arr.OrderBy(x => Random.Range(0f, 7f)).ToArray();
//4 * 4 행렬에 오브젝트 배치할때
//내가 자주 쓰는 방법
int[,] arr1 = new int[4, 4];
for(int y= 0; y < 4; y++)
{
for(int x = 0; x <4; x++)
{
GameObject go = Instantiate(card, this.transform);
go.transform.position = new Vector2(x * 1.0f - 1.5f, y * 1.0f - 4.5f);
go.GetComponent<Card>().Setting(arr[(x * 4) + y]);
}
}
//강의
for (int i = 0; i < 16; i++)
{
GameObject go = Instantiate(card, this.transform);
float x = (i % 4) * 1.0f - 1.5f; //나머지
float y = (i / 4) * 1.0f - 4.5f; // 몫
go.transform.position = new Vector2(x,y);
go.GetComponent<Card>().Setting(arr[i]);
}
x의 좌표 = (index % 4) * 벌어지는 간격 * 초기 x 좌표값 , y의 좌표 = (index / 4) * 벌어지는 간격 * 초기 y 좌표값
으로 반복문을 한번만 써서 만들수도 있다.
4.PixelPerUnit (PPU)
Unity에서 1유닛(Unit)에 포함되는 픽셀(Pixel)의 수를 의미한다.
우리가 아는 FPS에도 Frame per Second로 1초에 몇장의 Frame이 출력되냐 와 비슷한 의미이다.
일반적으로는 PPU는 실제 이미지 사이즈와 똑같이 설정을 많이 한다.
이미지 500 x 500의 원본사이즈 , PPU도 500으로 설정된 화면이다.
PPU가 500 일때 , 1유닛의 원본 사이즈 (500) : PPU (500) 으로 1x1 크기로 렌더링 된다.
하지만 PPU가 1000이 되면 , 1유닛의 원본사이즈(500) : PPU(1000) 로 하나의 유닛을 표현하는데 1000픽셀에 해당
됨으로 1000(PPU) x (렌더링 크기) = 500(원본사이즈) , 렌더링 사이즈 = 0.5로 0.5 x 0.5 크기로 렌더링 되는것이다.
게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발 5주차
1.안드로이드 빌드 환경 세팅하기
Key 생성을 하면 원하는 위치에 .keystore 파일이 생성된다.
2.Unity Ads를 통해 광고 붙이기 (테스트)
*메뉴얼 적용해서 Script 및 유니티 내부 변경
AsdInitalier Scripts에 https://docs.unity.com/ads/en-us/manual/InitializingTheUnitySDK 해당 코드 기입
RewardedAdsButton 에 https://docs.unity.com/ads/en-us/manual/ImplementingRewardedAdsUnity 해당 코드 기입
한국어 설정있으니 변경해서 참고하면 도움 많이 됨 , 만든 프로그램에 적용시키려면 코드 변경 필요함
1.게임 시작시 AdsInitalizer의 OnInitializationComplete() 통해 초기화 완료 알림
2.초기화 완료함에 따라 LoadAd()를 통해 광고를 미리 불러오기 알림
3.LoadAded()를 통해 광고가 불러져왔다는것을 알림
즉, 게임이 재시작 될때마다 광고 SDK 초기화 -> 광고 미리 불러오기 -> 광고 완료 -> 게임 완료 -> 끝(버튼)을 누르면
미리 불러온 광고를 재생 -> 광고의 close 버튼을 누르면 Scene 재로드
라는 로직으로 변경하였다.
변경한 AsdInitlaizer Scripts
using UnityEngine;
using UnityEngine.Advertisements;
public class AdsInitializer : MonoBehaviour, IUnityAdsLoadListener, IUnityAdsInitializationListener
{
[SerializeField] string _androidGameId;
[SerializeField] string _iOSGameId;
[SerializeField] bool _testMode = true;
private string _gameId;
[SerializeField] string _androidAdUnitId = "Rewarded_Android";
[SerializeField] string _iOSAdUnitId = "Rewarded_iOS";
string _adUnitId = null; // This will remain null for unsupported platforms
void Awake()
{
InitializeAds();
}
public void InitializeAds()
{
#if UNITY_IOS
_gameId = _iOSGameId;
_adUnitId = _iOSAdUnitId;
#elif UNITY_ANDROID
_gameId = _androidGameId;
_adUnitId = _androidAdUnitId;
#elif UNITY_EDITOR
_gameId = _androidGameId; //Only for testing the functionality in the Editor
_adUnitId = _androidAdUnitId;
#endif
if (!Advertisement.isInitialized && Advertisement.isSupported)
{
Advertisement.Initialize(_gameId, _testMode, this);
}
}
public void LoadAd()
{
// IMPORTANT! Only load content AFTER initialization (in this example, initialization is handled in a different script).
Debug.Log("Loading Ad: " + _adUnitId);
Advertisement.Load(_adUnitId, this);
}
public void OnInitializationComplete()
{
Debug.Log("Unity Ads initialization complete.");
LoadAd();
}
public void OnInitializationFailed(UnityAdsInitializationError error, string message)
{
Debug.Log($"Unity Ads Initialization Failed: {error.ToString()} - {message}");
}
public void OnUnityAdsAdLoaded(string placementId)
{
//throw new System.NotImplementedException();
Debug.Log("Ad Loaded: " + placementId);
}
public void OnUnityAdsFailedToLoad(string placementId, UnityAdsLoadError error, string message)
{
//throw new System.NotImplementedException();
}
}
변경한 RewardedAdsButton
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Advertisements;
using UnityEngine.SceneManagement;
public class RewardedAdsButton : MonoBehaviour, IUnityAdsLoadListener, IUnityAdsShowListener
{
//[SerializeField] Button _showAdButton; //버튼 오브젝트에 적용시킬거면 여기에 넣어 쓰면됨
//나는 글자를 버튼기능처럼 쓰려고 글자에 button 컴포넌트 넣고 주석처리함
[SerializeField] string _androidAdUnitId = "Rewarded_Android";
[SerializeField] string _iOSAdUnitId = "Rewarded_iOS";
string _adUnitId = null; // This will remain null for unsupported platforms
void Awake()
{
// Get the Ad Unit ID for the current platform:
#if UNITY_IOS
_adUnitId = _iOSAdUnitId;
#elif UNITY_ANDROID
_adUnitId = _androidAdUnitId;
#elif UNITY_EDITOR
_adUnitId = _androidAdUnitId;
#endif
// Disable the button until the ad is ready to show:
//_showAdButton.interactable = false;
}
// Call this public method when you want to get an ad ready to show.
public void LoadAd()
{
// IMPORTANT! Only load content AFTER initialization (in this example, initialization is handled in a different script).
Debug.Log("Loading Ad: " + _adUnitId);
Advertisement.Load(_adUnitId, this);
}
// If the ad successfully loads, add a listener to the button and enable it:
public void OnUnityAdsAdLoaded(string adUnitId)
{
Debug.Log("Ad Loaded: " + adUnitId);
if (adUnitId.Equals(_adUnitId))
{
// Configure the button to call the ShowAd() method when clicked:
//_showAdButton.onClick.AddListener(ShowAd);
// Enable the button for users to click:
//_showAdButton.interactable = true;
}
}
// Implement a method to execute when the user clicks the button:
public void ShowAd()
{
// Disable the button:
//_showAdButton.interactable = false;
// Then show the ad:
Advertisement.Show(_adUnitId, this);
}
// Implement the Show Listener OnUnityAdsShowComplete callback method to determine if the user gets a reward:
public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
{
if (adUnitId.Equals(_adUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
{
Debug.Log("Unity Ads Rewarded Ad Completed");
// Grant a reward.
LoadAd(); // 광고 불러오기
SceneManager.LoadScene("MainScene"); //광고 다 보면 메인 씬으로 이동하기
}
}
// Implement Load and Show Listener error callbacks:
public void OnUnityAdsFailedToLoad(string adUnitId, UnityAdsLoadError error, string message)
{
Debug.Log($"Error loading Ad Unit {adUnitId}: {error.ToString()} - {message}");
// Use the error details to determine whether to try to load another ad.
}
public void OnUnityAdsShowFailure(string adUnitId, UnityAdsShowError error, string message)
{
Debug.Log($"Error showing Ad Unit {adUnitId}: {error.ToString()} - {message}");
// Use the error details to determine whether to try to load another ad.
}
public void OnUnityAdsShowStart(string adUnitId) { }
public void OnUnityAdsShowClick(string adUnitId) { }
void OnDestroy()
{
// Clean up the button listeners:
//_showAdButton.onClick.RemoveAllListeners();
}
}
4.광고 추가하고 Build 오류 대처법
강의를 보고 광고를 추가 했을때 Build가 되지않아서 계속 터졌었다.
원인은 Build 시에 resolving android dependencies 가 자꾸 멈춰버리는 현상이 있었다.
https://meta-jun.tistory.com/253
https://stackoverflow.com/questions/50251836/unity-android-resolution-failed
Assets > Play Services Resolver > Android Resolver > Resolve
해당 두 글을 보고서 Build 문제를 해결 하였다.
Project Setting - Player - Android 환경에서 빨간 박스에 있는곳에 체크하면
위에서 체크하여 Android 폴더에 2개의 파일이 추가 된것을 확인 하였고
위에 설정들을 체크하고 resolving android dependencies 를 Resolve 하여 정상적으로 동작하는지
확인하고 Build를 하니 정상적으로 해결 되었다.
'내일배움캠프_Unity_6기 > TIL(Today I Learend)' 카테고리의 다른 글
TIL :: 2024-08-22(목) (0) | 2024.08.22 |
---|---|
TIL : 2024-08-21(수) (0) | 2024.08.21 |
TIL : 2024-08-19(월) (0) | 2024.08.19 |
TIL : 2024-08-16(금) (0) | 2024.08.16 |
TIL : 2024-08-14(수) (0) | 2024.08.14 |