XCode 빌드 시
Use of '@import' when modules are disabled
위와 같은 에러가 발생할 때 해결 방법!
- [Build Settings] 으로 이동
- modules 검색
- Enable Modules (C and Objectivce-C) 옵션을 No 에서 Yes 로 변경
끝 입니다 ^^
XCode 빌드 시
Use of '@import' when modules are disabled
위와 같은 에러가 발생할 때 해결 방법!
- [Build Settings] 으로 이동
- modules 검색
- Enable Modules (C and Objectivce-C) 옵션을 No 에서 Yes 로 변경
끝 입니다 ^^
Google Mobile Ads SDK (구글 애드몹) 를 사용하는 프로젝트를 XCode에서 빌드할 때
No visible @interface for 'GADUNativeCustomTemplateAd' declares the selector 'performClickOnAssetWithKey:customClickHandler:'
이런 에러가 발생한다면!?
GADUNativeCustomTemplateAd.h 파일로 이동합니다.
*nativeCustomTemplateAd 선언 부를 찾습니다.
@property(nonatomic, strong) GADUNativeCustomTemplateAd *nativeCustomTemplateAd;
위와 같이 되어있는 부분을
@property(nonatomic, strong) GADNativeCustomTemplateAd *nativeCustomTemplateAd;
이렇게 수정합니다. (GADU... -> GAD...)
다시 빌드하면 에러가 사라졌을 것입니다!
[iOS] Xcode에 CocoaPods 설치 및 사용하기 (1) | 2017.07.09 |
---|---|
[iOS] (Error) Use of '@import' when modules are disabled (0) | 2017.05.19 |
[iOS] Supporting IPv6-only networks (0) | 2017.01.19 |
[iOS] (Error) Terminating app due to uncaught exception 'NSUnknownKeyException' (0) | 2016.03.11 |
[iOS] (Error) ld: library not found for -lPods-Unity-iPhone (0) | 2016.03.08 |
마이크로소프트가 맥용 비쥬얼스튜디오 출시를 발표했습니다.
이제 더 이상 Mac Unity에서 MonoDevelop이 아닌 VisualStudio를 사용할 수 있게 되었습니다!
다운로드 사이트 링크 : https://www.visualstudio.com/ko/vs/visual-studio-mac
저도 소식을 접하자마자 바로 다운받았는데요!
VisualStudio를 실행한 모습입니다 ㅠㅠ
이제 Mac 환경에서도 디버깅을 할 수 있게되어 기쁘네요.
[Miscellaneous] 아마존 앱스토어에 앱 등록하기 (0) | 2017.05.29 |
---|---|
[Miscellaneous] 스마트폰 해상도별 대응을 위한 해상도 및 화면비율 표 (0) | 2017.01.19 |
[Miscellaneous] Manager, Handler, Controller (0) | 2016.07.11 |
[Miscellaneous] JNI (Java Native Interface) (0) | 2016.02.15 |
[Miscellaneous] Mac OS에서 Unity 프로젝트 여러개 띄우기 (0) | 2016.02.04 |
* 주의 : 이 스크립트는 유니티 에디터에서만 작동하고 런타임 중에는 사용할 수 없습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | //This script will only work in editor mode. You cannot adjust the scale dynamically in-game! using UnityEngine; using System.Collections; #if UNITY_EDITOR using UnityEditor; #endif [ExecuteInEditMode] public class ParticleScaler : MonoBehaviour { public float particleScale = 1.0f; public bool alsoScaleGameobject = true; float prevScale; void Start() { prevScale = particleScale; } void Update() { #if UNITY_EDITOR //check if we need to update if (prevScale != particleScale && particleScale > 0) { if (alsoScaleGameobject) transform.localScale = new Vector3(particleScale, particleScale, particleScale); float scaleFactor = particleScale / prevScale; //scale legacy particle systems ScaleLegacySystems(scaleFactor); //scale shuriken particle systems ScaleShurikenSystems(scaleFactor); //scale trail renders ScaleTrailRenderers(scaleFactor); prevScale = particleScale; } #endif } void ScaleShurikenSystems(float scaleFactor) { #if UNITY_EDITOR //get all shuriken systems we need to do scaling on ParticleSystem[] systems = GetComponentsInChildren<ParticleSystem>(); foreach (ParticleSystem system in systems) { system.startSpeed *= scaleFactor; system.startSize *= scaleFactor; system.gravityModifier *= scaleFactor; //some variables cannot be accessed through regular script, we will acces them through a serialized object SerializedObject so = new SerializedObject(system); //unity 4.0 and onwards will already do this one for us #if UNITY_3_5 so.FindProperty("ShapeModule.radius").floatValue *= scaleFactor; so.FindProperty("ShapeModule.boxX").floatValue *= scaleFactor; so.FindProperty("ShapeModule.boxY").floatValue *= scaleFactor; so.FindProperty("ShapeModule.boxZ").floatValue *= scaleFactor; #endif so.FindProperty("VelocityModule.x.scalar").floatValue *= scaleFactor; so.FindProperty("VelocityModule.y.scalar").floatValue *= scaleFactor; so.FindProperty("VelocityModule.z.scalar").floatValue *= scaleFactor; so.FindProperty("ClampVelocityModule.magnitude.scalar").floatValue *= scaleFactor; so.FindProperty("ClampVelocityModule.x.scalar").floatValue *= scaleFactor; so.FindProperty("ClampVelocityModule.y.scalar").floatValue *= scaleFactor; so.FindProperty("ClampVelocityModule.z.scalar").floatValue *= scaleFactor; so.FindProperty("ForceModule.x.scalar").floatValue *= scaleFactor; so.FindProperty("ForceModule.y.scalar").floatValue *= scaleFactor; so.FindProperty("ForceModule.z.scalar").floatValue *= scaleFactor; so.FindProperty("ColorBySpeedModule.range").vector2Value *= scaleFactor; so.FindProperty("SizeBySpeedModule.range").vector2Value *= scaleFactor; so.FindProperty("RotationBySpeedModule.range").vector2Value *= scaleFactor; so.ApplyModifiedProperties(); } #endif } void ScaleLegacySystems(float scaleFactor) { #if UNITY_EDITOR //get all emitters we need to do scaling on ParticleEmitter[] emitters = GetComponentsInChildren<ParticleEmitter>(); //get all animators we need to do scaling on ParticleAnimator[] animators = GetComponentsInChildren<ParticleAnimator>(); //apply scaling to emitters foreach (ParticleEmitter emitter in emitters) { emitter.minSize *= scaleFactor; emitter.maxSize *= scaleFactor; emitter.worldVelocity *= scaleFactor; emitter.localVelocity *= scaleFactor; emitter.rndVelocity *= scaleFactor; //some variables cannot be accessed through regular script, we will acces them through a serialized object SerializedObject so = new SerializedObject(emitter); so.FindProperty("m_Ellipsoid").vector3Value *= scaleFactor; so.FindProperty("tangentVelocity").vector3Value *= scaleFactor; so.ApplyModifiedProperties(); } //apply scaling to animators foreach (ParticleAnimator animator in animators) { animator.force *= scaleFactor; animator.rndForce *= scaleFactor; } #endif } void ScaleTrailRenderers(float scaleFactor) { //get all animators we need to do scaling on TrailRenderer[] trails = GetComponentsInChildren<TrailRenderer>(); //apply scaling to animators foreach (TrailRenderer trail in trails) { trail.startWidth *= scaleFactor; trail.endWidth *= scaleFactor; } } } | cs |
ParticleScaler.cs
위 스크립트를 ParticleSystem 오브젝트에 갖다붙이고
인스펙터에서 ParticleScale 변수를 조절해주면
모든 설정값들이 스케일 1 기준으로 딱딱딱 바뀌는 것을 볼 수 있습니다.
왼쪽은 원본 파티클이고 오른쪽은 ParticleScaler.cs 로 스케일 2배한 파티클입니다.
참 편리한 녀석이죠?
유용하게 쓰세요!
코드 출처 : https://github.com/hypno2000/starcontrol/blob/master/Assets/ParticleScaler/ParticleScaler.cs
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (2/2) #코드편 (13) | 2017.05.08 |
---|---|
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (1/2) #설정편 (2) | 2017.05.08 |
[Unity3D] Google AdMob 연동하기 (2) | 2017.04.22 |
[Unity3D] AdColony 연동하기 (0) | 2017.04.21 |
[Unity3D] Unity - Gitignore 설정하기 (0) | 2017.04.19 |
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (1/2) #설정편 링크 : http://minhyeokism.tistory.com/70
* 본격적으로 진행하기 전에 한 가지 말씀드리자면
UnityEngine.Social.localUser 는 Androiod와 iOS 두 플랫폼을 모두 지원하고
현재 앱의 Platform을 알아서 판단하여
Android는 구글 플레이 게임 서비스의 api를
iOS는 애플 게임선터의 api를 호출하도록 할 수 있습니다.
다시 말해,
1 2 3 4 | Social.localUser.Authenticate((bool success) => { }); | cs |
위 처럼 Social.localUser.~~~ 를 하면 Android 든 iOS 든 알아서! 문제없이! 작동한다는 뜻입니다.
그러나 특별한 상황에서는 구분을 명확하게 해야할 필요가 있습니다. 그럴 때에는
- Android일 경우 PlayGamesPlatform. 을
- iOS일 경우 GameCenterPlatform. 을
쓰시면 됩니다.
또한, iOS 앱에서도 PlayGamesPlatform.을 사용하면 게임센터가 아닌 구글 플레이에 로그인하도록 할 수도 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | void Start() { #if UNITY_ANDROID PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder() .EnableSavedGames() .Build(); PlayGamesPlatform.InitializeInstance(config); PlayGamesPlatform.DebugLogEnabled = true; PlayGamesPlatform.Activate(); #elif UNITY_IOS GameCenterPlatform.ShowDefaultAchievementCompletionBanner(true); #endif } | cs |
제일 먼저 Initialization과 Configuration 부분입니다.
구글의 저장된 게임 기능을 사용할 것이라면 (for Android)
.EnableSavedGames() 를 config에 추가해주세요.
마지막 줄에 PlayGamesPlatform.Activate() 를 해줘야 모든 기능이 작동합니다.
iOS는 특별한 config 빌드가 없어도 됩니다.
* 한 가지 주의할 점!
iOS 앱에서 안드로이드 용인 PlayGamesPlatform.Activate() 가 호출되면
애플 게임센터 api가 제대로 작동하지 않는 것을 경험했습니다.
때문에 게임센터에 접근하려면 위 처럼 코드를 #if 와 #elif 로 나눠주는 것이 좋습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public void SignIn() { Social.localUser.Authenticate((bool success) => { if (success) { // to do ... // 로그인 성공 처리 } else { // to do ... // 로그인 실패 처리 } }); } | cs |
Sign In 부분입니다.
Social.localUser로 Authenticate 하고 있기 때문에
Android와 iOS 둘 다 작동합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public void SignIn() { #if UNITY_ANDROID PlayGamesPlatform.Instance.Authenticate((bool success) => { if (success) { // to do ... // 구글 플레이 게임 서비스 로그인 성공 처리 } else { // to do ... // 구글 플레이 게임 서비스 로그인 실패 처리 } }); #elif UNITY_IOS Social.localUser.Authenticate((bool success) => { if (success) { // to do ... // 애플 게임 센터 로그인 성공 처리 } else { // to do ... // 애플 게임 센터 로그인 실패 처리 } }); #endif } | cs |
필요에 따라 이렇게 명확하게 구분하여 구현해도 됩니다.
(GameCenterPlatform 에는 Authenticate가 없기때문에 Social.localUser로 접근함)
플레이 게임 서비스 Sign Out 은 이렇게 하시면 됩니다.
(게임 센터 Sign Out api는 별도로 확인하지 못 함)
다음으로 업적과 리더보드를 구현해보겠습니다.
1 2 3 4 5 6 7 8 9 10 11 | public void UnlockAchievement(int score) { if (score >= 100) { #if UNITY_ANDROID PlayGamesPlatform.Instance.ReportProgress(GPGSIds.achievement_100, 100f, null); #elif UNITY_IOS Social.ReportProgress("Score_100", 100f, null); #endif } } | cs |
먼저, 업적을 잠금해제하는 코드 예시입니다.
Social.ReportProgress("업적ID", 0f~100f, callback);
첫 번째 파라미터에는 잠금해제 할 업적의 고유 ID를 입력해주고
(설정편에서 생성된 GPGSIds.cs에 있는 static 변수를 가져다 쓸 것)
두 번째 파라미터에는 해당 업적의 진행도(0f~100f) 를 넣어줍니다.
진행도가 존재하는 업적의 경우 진행도를 0과 100사이의 float형으로 환산하여 넣어주면 되고
단순히 조건을 충족하면 바로 잠금해제되는 업적일 경우 바로 100f를 넣어주면 됩니다.
세 번째 파라미터에는 callback 함수를 넣어줍니다.
콜백이 필요 없는 경우에는 null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public void ShowAchievementUI() { // Sign In 이 되어있지 않은 상태라면 // Sign In 후 업적 UI 표시 요청할 것 if (Social.localUser.authenticated == false) { Social.localUser.Authenticate((bool success) => { if (success) { // Sign In 성공 // 바로 업적 UI 표시 요청 Social.ShowAchievementsUI(); return; } else { // Sign In 실패 처리 return; } }); } Social.ShowAchievementsUI(); } | cs |
업적 UI를 열려면
Social.ShowAchievementsUI() 를 호출하면 됩니다.
* 소셜에 로그인이 되어있지 않다면 로그인 후 재요청하는 예외처리를 해주는 것이 좋습니다.
좌 : Android - Google Play Games Services 업적 UI 스크린샷
우 : iOS - Apple Game Center 목표 달성 UI 스크린샷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public void ReportScore(int score) { #if UNITY_ANDROID PlayGamesPlatform.Instance.ReportScore(score, GPGSIds.leaderboard_score, (bool success) => { if (success) { // Report 성공 // 그에 따른 처리 } else { // Report 실패 // 그에 따른 처리 } }); #elif UNITY_IOS Social.ReportScore(score, "Leaderboard_ID", (bool success) => { if (success) { // Report 성공 // 그에 따른 처리 } else { // Report 실패 // 그에 따른 처리 } }); #endif } | cs |
다음은 리더보드에 점수를 기록하는 코드 예시입니다.
Social.ReportScore(점수, "리더보드 고유 ID", callback);
첫 번째 파라미터에는 플레이어가 기록한 점수를 넣어줍니다.
두 번째 파라미터에는 점수를 올릴 리더보드의 고유 ID를 넣어줍니다.
(설정편에서 생성된 GPGSIds.cs에 있는 static 변수를 가져다 쓸 것)
세 번째 파라미터에는 callback 함수를 넣어줍니다.
콜백이 필요 없는 경우에는 null
* ReportScore() 함수 내부에서 플레이어의 기록된 점수와 파라미터로 날아온 점수의 높낮이를 비교하고 필터링하기 때문에
더 낮은 점수일 경우의 예외처리를 할 필요가 없습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public void ShowLeaderboardUI() { // Sign In 이 되어있지 않은 상태라면 // Sign In 후 리더보드 UI 표시 요청할 것 if (Social.localUser.authenticated == false) { Social.localUser.Authenticate((bool success) => { if (success) { // Sign In 성공 // 바로 리더보드 UI 표시 요청 Social.ShowLeaderboardUI(); return; } else { // Sign In 실패 // 그에 따른 처리 return; } }); } #if UNITY_ANDROID PlayGamesPlatform.Instance.ShowLeaderboardUI(); #elif UNITY_IOS GameCenterPlatform.ShowLeaderboardUI("Leaderboard_ID", UnityEngine.SocialPlatforms.TimeScope.AllTime); #endif } | cs |
리더보드의 UI를 열려면
Social.ShowLeaderboardUI()
PlayGamesPlatform.Instance.ShowLeaderboardUI()
GameCenterPlatform.ShowLeaderboardUI("순위표 고유 ID", TimeScope)
를 상황에 맞게 호출합니다.
* 마찬가지로, 소셜에 로그인이 되어있지 않다면 로그인 후 재요청하는 예외처리를 해주도록 합니다.
리더보드 UI를 열 때
위 처럼 TimeScope 를 정해서 넘겨주면 원하는 기간동안의 순위표를 보게할 수도 있습니다.
AllTime - 전체 기간 순위표
Today - 오늘 순위표
Week - 이번 주 순위표
Android - Google Play Games Services 리더보드 UI 스크린샷
iOS - Apple Game Center 순위표 UI 스크린샷
이상으로 포스팅을 마치겠습니다.
궁금한 점이 있다면 댓글 남겨주세요.
[Unity3D] 파티클 사이즈 조절을 쉽게 할 수 있는 ParticleScaler.cs (5) | 2017.05.11 |
---|---|
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (1/2) #설정편 (2) | 2017.05.08 |
[Unity3D] Google AdMob 연동하기 (2) | 2017.04.22 |
[Unity3D] AdColony 연동하기 (0) | 2017.04.21 |
[Unity3D] Unity - Gitignore 설정하기 (0) | 2017.04.19 |
안녕하세요.
이번 포스팅의 주제는 Google Play Games 플러그인 연동하기 입니다!
유니티 프로젝트에
Android - 구글 플레이 게임 서비스 (Google Play Games Services)
iOS - 애플 게임 샌터 (Apple Game Center)
를 연동하고
1. 로그인(SignIn), 2. 로그아웃(SignOut), 3. 업적(Achievement), 4. 리더보드(Leaderboard)
기능을 구현해보도록 하겠습니다.
물론 Google Play Games plugin for Unity - Github 사이트에 영문으로
업적, 리더보드, 저장된 게임, 퀘스트 등 다양한 기능 연동 가이드가 있습니다.
링크 : https://github.com/playgameservices/play-games-plugin-for-unity
우선 위 링크에서 [Clone or download] -> [Download.ZIP] 하여 플러그인을 다운로드합니다.
압축을 풀고 내용물을 보면
이렇게 되어있는데
맨 위 current-build 폴더에 최신 버전 플러그인.unitypackage가 들어있습니다.
(이 플러그인은 구글 플레이 게임서비스와 애플 게임센터 두 플랫폼 다 지원함)
유니티 프로젝트에 import 해둡니다.
[Android - 구글 플레이 게임 서비스 설정]
먼저, 구글 플레이 개발자 콘솔로 이동하여 (회원가입 후) 로그인 합니다.
플레이 콘솔 사이트 링크 : https://play.google.com/apps/publish/?hl=ko
(Google Play Developer Console의 탐색 기능과 디자인이 업데이트되었으며 이름이 Play Console로 변경되었습니다 - 17년 4월 기준)
우측에 [애플리케이션 만들기] 버튼을 클릭합니다. (플레이 콘솔에 앱을 추가하지 않은 경우만)
언어를 설정하고 제목을 입력한 후 [만들기] 하고
스토어 등록정보 등 기타 내용을 채워서 출시 조건을 맞춰줍니다.
애플리케이션 설정을 완료했다면 [게임 서비스]로 이동하여 [새 게임 추가]를 클릭합니다.
게임 이름을 입력하고 카테고리 선택 후 [계속] 합니다.
애플리케이션 설정과 마찬가지로 [게임 세부정보]에 내용을 채워줍니다.
그 다음 [연결된 앱]으로 이동하고 플랫폼을 선택합니다.
이전에 만들어 두었던 애플리케이션을 게임 서비스와 연결하는 과정입니다.
앱 이름과 패키지 이름, 기타 설정을 마치고 [저장하고 계속] 합니다.
연결이 정상적으로 완료된 모습입니다.
업적과 리더보드를 각각 추가해줍니다.
(참고로, 업적이나 리더보드 아이콘을 넣어주지 않으면 디폴트 아이콘이 보여집니다.)
그러고 나면 하단에 [리소스 받기] 가 보이실텐데요 한번 클릭해 봅시다.
위 처럼 [리소스 내보내기] 라고 뜨는데요
Android 앱은 [ANDROID] 탭을 눌러서 내용을 복사해둡니다.
(iOS 앱은 [OBJECTIVE-C] 탭을 눌러서 복사)
이제 유니티로 돌아옵니다.
플러그인이 정상적으로 임포트 되었다면 Window에 Google Play Games 메뉴가 생깁니다.
그럼 [Window] -> [Google Play Games] -> [Setup] -> [Android setup] 해줍니다.
위와 같은 팝업창이 뜨면 [Resources Definition]에
아까 복사해 두었던 리소스를 붙여넣기 합니다.
[Web App Client ID]는 웹 게임용 변수이므로 패스하고 [Setup] 버튼을 누릅니다.
Setup이 완료되었습니다.
[OK]를 누르고 로딩을 기다리면
위 처럼 GPGSIds 라는 .cs 파일이 생성되었을 것입니다.
앞서 만들어둔 업적과 리더보드의 ID를 string 형식으로 담고있는 모습입니다.
업적을 잠금해제하거나 리더보드에 스코어를 올릴 때
위 static 클래스 GPGSIds의 string 변수를 가져다 쓸 것입니다.
[iOS - 애플 게임센터 설정]
아이튠즈 커넥트 사이트로 이동하여 회원가입 후 로그인 합니다.
iTunes Connect 사이트 링크 : https://itunesconnect.apple.com
로그인 후 메인 페이지에서 [나의 앱] 으로 이동합니다.
[나의 앱] 페이지 좌상단에 있는 [+ 버튼] 을 누른 후 [신규 앱] 을 클릭합니다.
이미 등록된 앱이 있다면 앱 아이콘을 클릭합니다.
플랫폼, 이름, 기본 언어, 번들 ID, SKU 를 입력하고 [생성] 합니다.
앱이 정상적으로 생성되었다면 앱 아이콘을 눌러 앱 페이지로 이동합니다.
그 다음 [앱 내 추가 기능] -> [Game Center] 메뉴로 이동합니다.
순위표와 목표 달성 (각각 리더보드와 업적을 뜻함) 이
비어있는 모습입니다.
먼저 순위표 옆에 있는 +버튼을 눌러줍니다.
개별 순위표를 [선택] 합니다.
개별 순위표 정보를 채워줍니다.
그리고 하단 순위표 현지화에 있는 [언어 추가] 를 눌러줍니다.
현지화 할 언어를 선택합니다.
나머지 정보를 입력하고 (이미지는 선택사항, 이미지를 올리지 않으면 디폴트 이미지가 보여짐) [Save] 합니다.
이제 리더보드가 준비되었습니다.
다음으로 업적을 추가해 봅시다.
목표 달성 옆에 있는 +버튼을 눌러서 업적을 생성합니다.
업적 정보를 입력하고 하단 목표 달성 현지화에 있는 [언어 추가] 를 눌러줍니다.
마찬가지로 현지화 할 언어를 선택하고 제목과 설명을 입력하고 [Save] 합니다.
위는, 업적 아이콘을 원하는 이미지로 직접 설정해 준 모습입니다.
다시 유니티로 돌아와서
[Window] -> [Google Plat Games] -> [Setup] -> [iOS setup...] 합니다.
팝업 창이 뜨면 플레이 콘솔 [리소스 내보내기] 에서 [OBJECTIVE-C] 를 선택하고
복사 & 붙여넣기 합니다.
그리고 [Setup] 해줍니다.
자, 이제 정말로 연동할 준비가 다 되었습니다!
다음 편에 계속됩니다!
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (2/2) #코드편 링크 : http://minhyeokism.tistory.com/72
[Unity3D] 파티클 사이즈 조절을 쉽게 할 수 있는 ParticleScaler.cs (5) | 2017.05.11 |
---|---|
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (2/2) #코드편 (13) | 2017.05.08 |
[Unity3D] Google AdMob 연동하기 (2) | 2017.04.22 |
[Unity3D] AdColony 연동하기 (0) | 2017.04.21 |
[Unity3D] Unity - Gitignore 설정하기 (0) | 2017.04.19 |
이번에는 유니티에 구글 애드몹 SDK를 연동하여 [Banner 광고]와 [Interstitial 광고]를 달아보도록 하겠습니다.
우선 AdMob 홈페이지에 들어가서 회원가입 후 로그인 합니다.
Google AdMob 사이트 링크 : http://www.google.co.kr/admob
홈페이지에서 [수익 창출] -> [+새로운 앱에서 수익 창출] 합니다.
1. 앱 선택
이미 스토어에 올라간 앱이라면 [앱 검색]
개발 중인 앱이라면 [앱 직접 추가]
이미 추가된 앱의 광고를 생성하려면 [추가한 앱 중에서 선택]
본 포스팅에서는 개발 중인 앱이라 가정하고 [앱 직점 추가] 로 진행
앱 이름과 플랫폼을 선택 후 [앱 추가] 를 누릅니다.
이제 ca-app-pub 로 시작하는 앱 ID가 생성되었음을 볼 수 있습니다.
2. 광고 형식 선택 및 광고 단위 이름 지정
먼저 [배너] 를 선택해주고
[광고 유형] [자동 새로고침] [텍스트 광고 스타일] [광고 단위 이름] 모두 설정해주고 [저장] 을 누릅니다.
앱 ID와 마찬가지로 [광고 단위 ID] 도 생성되었습니다.
3. Firebase 애널리틱스 설정(선택사항)
Firebase 애널리틱스 관련 내용은 다음에 포스팅 할 예정이니 [건너 뛰기] 누릅니다.
4. 구현 안내 보기
Banner 광고 생성을 완료하였으니
Interstitial 광고(전면 광고)도 생성하기 위해 [다른 광고 단위 생성] 합니다.
[전면] 을 선택하고
[광고 유형] 과 [게재빈도 설정] 및 [광고 단위 이름] 을 설정하고 [저장] 합니다.
배너 광고 단위와 전면 광고 단위가 잘 생성되었음을 볼 수 있습니다.
이제 본격적으로 유니티에 연동할 차례입니다.
우선 아래 링크에서 AdMob Unity Plugin(GoogleMobileAds.unitypackage)을 다운로드 받습니다.
Google AdMob Unity Plugin(v3.4.0) 다운로드 링크 : https://github.com/googleads/googleads-mobile-unity/releases/tag/v3.4.0
다운로드한 unitypackage를 유니티 프로젝트에 import 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | using UnityEngine; using System; using GoogleMobileAds.Api; public class AdMobManager : MonoBehaviour { public string android_banner_id; public string ios_banner_id; public string android_interstitial_id; public string ios_interstitial_id; private BannerView bannerView; private InterstitialAd interstitialAd; public void Start() { RequestBannerAd(); RequestInterstitialAd(); ShowBannerAd(); } public void RequestBannerAd() { string adUnitId = string.Empty; #if UNITY_ANDROID adUnitId = android_banner_id; #elif UNITY_IOS adUnitId = ios_bannerAdUnitId; #endif bannerView = new BannerView(adUnitId, AdSize.SmartBanner, AdPosition.Top); AdRequest request = new AdRequest.Builder().Build(); bannerView.LoadAd(request); } private void RequestInterstitialAd() { string adUnitId = string.Empty; #if UNITY_ANDROID adUnitId = android_interstitial_id; #elif UNITY_IOS adUnitId = ios_interstitialAdUnitId; #endif interstitialAd = new InterstitialAd(adUnitId); AdRequest request = new AdRequest.Builder().Build(); interstitialAd.LoadAd(request); interstitialAd.OnAdClosed += HandleOnInterstitialAdClosed; } public void HandleOnInterstitialAdClosed(object sender, EventArgs args) { print("HandleOnInterstitialAdClosed event received."); interstitialAd.Destroy(); RequestInterstitialAd(); } public void ShowBannerAd() { bannerView.Show(); } public void ShowInterstitialAd() { if (!interstitialAd.IsLoaded()) { RequestInterstitialAd(); return; } interstitialAd.Show(); } } | cs |
AdMobManager.cs를 생성하고 위 코드를 복사 붙여넣기 합니다.
빈 게임 오브젝트를 생성하고 AdMobManager.cs를 Add Componet 해줍니다.
플랫폼 별로, banner_id 와 interstitial_id 변수 값에 앞서 얻은 id를 각각 입력해줍니다.
AdMob은 RequestAd() 로 광고를 요청하고 요청에 성공하면 ShowAd()로 광고를 송출하는 형식입니다.
배너광고는 이니셜라이즈 시 Request 하고 바로 Show 합니다.
전면광고는 미리 Request 로 캐싱해 두다가 원하는 상황에 Show 한 후 광고가 닫히면 재요청하는 구조입니다.
메모리 누수를 방지하기 위해
HandleOnInterstitialAdClosed 콜백에서 interstitialAd.Destroy(); 를 해주도록 합니다.
BannerView를 생성할 때 파라미터로 사이즈와 위치를 조절할 수 있는데요
AdSize.SmartBanner 로 설정해주면 디바이스의 해상도에 맞춰서 자동으로 크기 조절이 되고
AdPosition 파라미터로 배너의 위치를 조절할 수 있습니다.
위 스크린샷은 배너가 AdPosition.Top 으로 설정된 모습입니다.
전면 광고는 게임 오버나 버프 지급 등 특정 상황에 송출하도록 합니다.
RequestInterstitialAd() 로 캐싱해 두었던 전면광고를
원하는 상황에 ShowAd() 해줌으로써 광고를 송출시킵니다.
광고 시청이 완료되면 HandleOnInterstitialAdClosed 콜백이 호출되는데
콜백 안에 광고 시청에 대한 보상을 지급하고
RequestInterstitialAd() 로 소모된 광고를 미리 재 요청해놓습니다.
게임 내 애드몹 전면광고가 송출된 모습입니다.
이상으로 포스팅을 마치도록 하겠습니다.
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (2/2) #코드편 (13) | 2017.05.08 |
---|---|
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (1/2) #설정편 (2) | 2017.05.08 |
[Unity3D] AdColony 연동하기 (0) | 2017.04.21 |
[Unity3D] Unity - Gitignore 설정하기 (0) | 2017.04.19 |
[Unity3D] Unity Ads 연동하기 (4) | 2017.04.19 |
이번에는 Unity 프로젝트에 AdColony SDK 연동을 해보겠습니다! (역시 매우 간단)
AdColony 홈페이지 링크 : https://www.adcolony.com
AdColony SDK 다운로드 링크 : https://github.com/AdColony/AdColony-Unity-SDK-3
위의 AdColony GitHub 링크로 가서
[Clone or download -> Download ZIP]
한 후, 다운로드 받은 애드콜로니 유니티패키지를 프로젝트에 import 합니다.
다음으로 진행하기 전에 기본적인 세팅이 필요한데요
우선 애드콜로니에 회원가입하고 로그인 합니다.
그 다음 [MONETIZATION] 탭에서 [Setup New App] 을 클릭합니다
App의 Platform과 국가, 이름
광고를 Skip 가능하게 할 지와
13세 미만 어린이에게 지도 감독이 필요한 앱인지 여부를 체크합니다.
그리고 앱의 특성이나 출시 국가에 따라 다르겠지만 웬만한 정책위반을 피하기 위해
되도록이면 [Customize Your Ads] 부분에 정치, 종교, 성인 등의 광고 타입은 체크해제 해주는 것이 좋습니다.
모든 세팅이 완료되면 [Create] 합니다.
아래는 광고 App의 기본적 Setup이 완료된 모습입니다.
[AdColony App ID] 는 스크립트를 작성할 때 필요하므로 잘 기억해둡니다.
하단에 디폴트로 생선된 Zone [Ad Zone #1] 이 보일텐데 Zone 세팅을 위해 클릭해줍니다.
[Zone is active] - Yes 해주고
[Zone ID] 도 [AdColony App ID] 와 마찬가지로 스크립트 작성에 필요하므로 잘 기억해둡니다.
Zone Name과 Creative Type을 설정해줍니다. (우리는 비디오 광고를 연동할 것이기 때문에 Video로 설정)
그 다음 [Zone Type] 을 아래와 같이
Value Exchange/V4VC 로 설정해줍니다.
모든 설정을 마치면 [Save] 합니다.
여기까지 되었다면 다시 유니티로 돌아와서
AdColonyManager 라는 스크립트를 만들고
아래의 코드를 복사 붙여넣기 합니다.
애드콜로니 사이트에서 App 세팅할 때 보았던
[AdColony App ID] 와 [Zone ID] 를 각각 플랫폼별 id 변수에 넣어줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | using UnityEngine; using System.Collections.Generic; public class AdColonyManager : MonoBehaviour { private const string android_appId = "xxxxxxxxxxxxxxxxxxx"; private const string android_zoneId = "xxxxxxxxxxxxxxxxxxx"; private const string ios_appId = "xxxxxxxxxxxxxxxxxxx"; private const string ios_zoneId = "xxxxxxxxxxxxxxxxxxx"; private string appId = string.Empty; private string zoneId = string.Empty; private AdColony.InterstitialAd ad = null; void Start() { Initialize(); } private void Initialize() { #if UNITY_ANDROID this.appId = android_appId; this.zoneId = android_zoneId; #elif UNITY_IOS this.appId = ios_appId; this.zoneId = ios_zoneId; #endif AdColony.Ads.OnConfigurationCompleted += (List<AdColony.Zone> zones_) => { Debug.Log("AdColony.Ads.OnConfigurationCompleted called"); if (zones_ == null || zones_.Count <= 0) { Debug.Log("Configure Failed"); } else { Debug.Log("Configure Succeeded."); } }; AdColony.Ads.OnRequestInterstitial += (AdColony.InterstitialAd ad_) => { Debug.Log("AdColony.Ads.OnRequestInterstitial called"); ad = ad_; // to do ... // 광고 요청에 성공했을 때 처리 ShowAd(); }; AdColony.Ads.OnRequestInterstitialFailed += () => { Debug.Log("AdColony.Ads.OnRequestInterstitialFailed called"); // to do ... // 광고 요청에 실패했을 때 처리 }; AdColony.Ads.OnOpened += (AdColony.InterstitialAd ad_) => { Debug.Log("AdColony.Ads.OnOpened called"); }; AdColony.Ads.OnClosed += (AdColony.InterstitialAd ad_) => { Debug.Log("AdColony.Ads.OnClosed called, expired: " + ad_.Expired); }; AdColony.Ads.OnExpiring += (AdColony.InterstitialAd ad_) => { Debug.Log("AdColony.Ads.OnExpiring called"); }; AdColony.Ads.OnRewardGranted += (string zoneId, bool success, string name, int amount) => { Debug.Log(string.Format("AdColony.Ads.OnRewardGranted called\n\tzoneId: " + "{0}\n\tsuccess: {1}\n\tname: {2}\n\tamount: {3}", zoneId, success, name, amount)); if (success) { // to do ... // 광고 시청이 완료되었을 때 처리 // 광고 시청에 대한 보상 지급 등 ... } }; AdColony.AppOptions appOptions = new AdColony.AppOptions(); appOptions.AdOrientation = AdColony.AdOrientationType.AdColonyOrientationAll; AdColony.Ads.Configure(this.appId, appOptions, this.zoneId); } public void RequestAd() { Debug.Log("**** Request Ad ****"); AdColony.AdOptions adOptions = new AdColony.AdOptions(); adOptions.ShowPrePopup = false; adOptions.ShowPostPopup = false; AdColony.Ads.RequestInterstitialAd(this.zoneId, adOptions); } public void ShowAd() { Debug.Log("**** Show Ad ****"); if (this.ad != null) { AdColony.Ads.ShowAd(this.ad); } } } | cs |
RequestAd() 함수로 광고 요청을 보낸 후
요청에 성공했다면 OnRequestInterstitial 콜백을 타고
ShowAd() 함수를 호출되는 구조입니다. (요청에 실패하면 OnRequestInterstitialFailed 콜백)
그리고 ShowAd() 로 광고 시청이 완료되면
OnRewardGranted 콜백이 호출되므로 (success == true)
콜백 안에 광고 시청에 대한 보상을 지급하는 코드를 작성해주면 됩니다.
* 광고 procedure
Initialize() -> RequestAd() -> OnRequestInterstitial -> ShowAd() -> OnRewardedGranted
위와 같은 절차로 여러분의 프로젝트에 코드를 녹여주시고
OnRequestInterstitialFailed 나 OnExpiring 등 기타 콜백함수도 입맛에 맞게 정의해주시면 되겠습니다.
참고로 AdColony는 UnityAds와 다르게 Editor 상에서는 테스트가 불가능하므로 모바일에서 테스트해보시길 바랍니다!
[Unity3D] 구글 플레이 게임 서비스 & 애플 게임 센터 연동 (1/2) #설정편 (2) | 2017.05.08 |
---|---|
[Unity3D] Google AdMob 연동하기 (2) | 2017.04.22 |
[Unity3D] Unity - Gitignore 설정하기 (0) | 2017.04.19 |
[Unity3D] Unity Ads 연동하기 (4) | 2017.04.19 |
[Unity3D] SoundVisualizer 만들기 (1) | 2017.03.19 |
Git을 통해 버전 관리를 할 때
Gitignore를 이용하면 특정 파일을 버전 컨트롤에서 제외시킬 수 있습니다.
이는 쓸모없는 파일이나 원하지 않는 파일을 commit에서 제외시켜 merge crash를 예방하기 위함인데요
아래는 Unity 프로젝트의 gitignore 목록입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | # =============== # # Unity generated # # =============== # Temp/ Obj/ UnityGenerated/ Library/ # ===================================== # # Visual Studio / MonoDevelop generated # # ===================================== # ExportedObj/ *.svd *.userprefs *.csproj *.pidb *.suo *.sln *.user *.unityproj *.booproj # ============ # # OS generated # # ============ # .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes Icon? ehthumbs.db Thumbs.db GraphicsSettings.asset ProjectSettings.asset ProjectVersion.txt | cs |
.gitignore 라는 파일을 만들고
위 Text를 복사하여 붙여넣고 저장합니다.
그리고나면 Unity에서도 git을 무리없이 사용할 수 있습니다.
[Unity3D] Google AdMob 연동하기 (2) | 2017.04.22 |
---|---|
[Unity3D] AdColony 연동하기 (0) | 2017.04.21 |
[Unity3D] Unity Ads 연동하기 (4) | 2017.04.19 |
[Unity3D] SoundVisualizer 만들기 (1) | 2017.03.19 |
[Unity3D] 안드로이드 App 실행 후 퍼미션 요청 스킵하는 방법 (SkipPermissionsDialog) (1) | 2017.01.19 |
이번에는 Unity 프로젝트에 Unity Ads를 연동해보겠습니다. (매우 간단 주의)
우선 Unity에서 [Window -> Services] 하면 인스펙터 뷰 옆에 아래와 같은 화면이 나타나는데
Ads 항목이 OFF(디폴트)로 되어있는 것을 볼 수 있습니다.
Ads 항목을 클릭하면 아래와 같이 나오는데
토글 버튼을 눌러 비활성화되어있는 Ads를 활성화 시킵니다.
13세 미만 아이들에게 지도감독이 필요한 앱인지 여부를 설정하고 Continue 합니다.
활성화가 완료되면 아래와 같이 나옵니다.
원하는 Platform을 체크합니다.
Enable test mode를 체크하면 유니티에서 제공하는 짧은 테스트 광고영상만 송출됩니다.
(런칭 시 반드시 위 항목 체크를 해제할 것)
여기까지 완료했다면,
using UnityEngine.Advertisements;
를 할수있게 됩니다!
UnityAdsHelper라는 C# 스크립트를 하나 생성하고
아래의 코드를 복사해서 붙여 넣습니다.
그 다음, 빈 게임 오브젝트를 하나 생성하고 UnityAdsHelper.cs를 AddComponent 해줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | using UnityEngine; using UnityEngine.Advertisements; public class UnityAdsHelper : MonoBehaviour { private const string android_game_id = "xxxxxxx"; private const string ios_game_id = "xxxxxxx"; private const string rewarded_video_id = "rewardedVideo"; void Start() { Initialize(); } private void Initialize() { #if UNITY_ANDROID Advertisement.Initialize(android_game_id); #elif UNITY_IOS Advertisement.Initialize(ios_game_id); #endif } public void ShowRewardedAd() { if (Advertisement.IsReady(rewarded_video_id)) { var options = new ShowOptions { resultCallback = HandleShowResult }; Advertisement.Show(rewarded_video_id, options); } } private void HandleShowResult(ShowResult result) { switch (result) { case ShowResult.Finished: { Debug.Log("The ad was successfully shown."); // to do ... // 광고 시청이 완료되었을 때 처리 break; } case ShowResult.Skipped: { Debug.Log("The ad was skipped before reaching the end."); // to do ... // 광고가 스킵되었을 때 처리 break; } case ShowResult.Failed: { Debug.LogError("The ad failed to be shown."); // to do ... // 광고 시청에 실패했을 때 처리 break; } } } } | cs |
위 코드는
ShowRewardedAd() 함수로 비디오 광고 송출 요청을 하고
HandleShowResult 콜백으로 요청 결과에 따라 Finished, Skipped, Failed 처리하는 구조로 되어있습니다.
* 여기서 androiod game id와 ios game id 그리고 rewarded video id가 필요한데
Services의 우측 상단에 있는 Go to Dashboard 를 누르면
아래와 같은 화면이 뜨는데
여기서 android 게임 ID와 ios 게임 ID를 확인할 수 있습니다.
UnityAdsHelper.cs의 android_game_id 변수와 ios_game_id 변수에 Game Id 숫자 7자리를 각각 넣어주시면 됩니다.
그 다음, 구글 플레이 스토어 또는 애플 앱 스토어 플랫폼을 클릭하여 Ad placements 정보를 확인합니다.
기본적으로 Video와 Rewarded Video 두 가지가 생성되어있는데
첫 번째에 있는 Video는 Skip이 가능한 광고이고
두 번째에 있는 Rewarded Video는 Skip이 불가능한 보상형 광고입니다.
수익을 많이 내려면 당연히 Skip이 불가능한 보상형 광고를 써야겠죠?
위 스크린샷 처럼 Rewarded Video를 Enabled 하고 Default로 설정합니다. (우측에 EDIT 버튼으로 세부설정이 가능함)
그리고 Rewarded Video의 PLACEMENT ID를 복사하여
UnityAdsHelper.cs의 rewarded_video_id 변수에 넣어줍니다.
----------------------------------------------------------------------------------
자, 모든 준비가 끝났습니다!
Unity Editor에서 ShowRewardedAd()로 광고를 요청했을 때 아래와 같은 화면이 나온다면
정상적으로 연동된 것입니다.
이제 원하는 상황에 ShowRewardedAd() 함수를 호출하고 (주로 게임 오버될 때 혹은 특정 버프를 받을 때)
HandleShowResult 콜백에서 원하는 처리를 하여 마무리해줍니다. (캐릭터 부활 혹은 버프효과 적용 등)
[Unity3D] AdColony 연동하기 (0) | 2017.04.21 |
---|---|
[Unity3D] Unity - Gitignore 설정하기 (0) | 2017.04.19 |
[Unity3D] SoundVisualizer 만들기 (1) | 2017.03.19 |
[Unity3D] 안드로이드 App 실행 후 퍼미션 요청 스킵하는 방법 (SkipPermissionsDialog) (1) | 2017.01.19 |
[Unity3D] Unity In App Purchasing / In App Billing - iOS & Android (26) | 2016.07.08 |