레이블이 프로그래밍인 게시물을 표시합니다. 모든 게시물 표시
레이블이 프로그래밍인 게시물을 표시합니다. 모든 게시물 표시

2019년 9월 5일 목요일

Unity Canvas Render Mode 설정

UGUI의 Canvas 설정 중 Render Mode 를 정리한다.
이는 2D 게임 개발 중 Canvas > Particle > Canvas 의 출력 순서를 정의하기 위한 복습 자료이다.


  1. 2D 게임을 만들면서 Main Camera가 Orthographic인 설정에서 Screen Space - Camera 모드로 설정한 Canvas를 복수로 설정하는 것이 좋다. 
  2. 이는 Canvas의 Sorting Layer와 Sort Order의 설정을 통해 Depth를 지정 한다. 
  3. 그리고 Particle System의 Renderer 항목의 Sorting Layer와 Sort Order의 설정을  Canvas 사이로 설정해 Particle 출력의 효과를 발생시킬 수 있다. 


Screen Space - Overlay 모드 

  • 캔버스가 씬 내부의 어느 곳에 있더라도 화면 전체를 덮는 모습으로 렌더링 된다.
  • Pixel Perfect
    - On으로 지정하면 UI의 픽셀의 색 그대로 표현하도록 렌더링 함
    - 경계면이 명확히 표현할 수 있음(안티 앨리어싱 없이 렌더링)
    - 다양한 UI 연출로 인한 퍼포먼스를 위해서는 Off로 사용하기를 권장
  • Sort Order
    - 렌더링 되는 순서를 수치로 설정
    - 값이 작을수록 안쪽에 렌더링 됨 


Screen Space - Camera 모드 

  • 지정된 카메라와 일정한 거리만큼 떨어진 앞쪽에 위치 
  • 카메라의 Projection 속성이 Perspective로 지정된 경우 UI 요소는 원근감이 느껴지도록 렌더링 됨 (원근감의 정도는 Field of View 속성값에 의해 결정)
  • Pixel Perfect
    - On으로 지정하면 UI의 픽셀의 색 그대로 표현하도록 렌더링 함
  • Render Camera
    - 캔버스를 렌더링할 카메라를 지정
  • Plane Distance
    - 카메라에서 캔버스까지의 거리를 설정
  • Sorting Layer
    - 캔버스의 소팅 레이어(Sorting Layer)를 지정.
    - 소팅 레이어란 2D 스프라이트를 포함한 2D 그래픽을 렌더링하는 순서를 제어하는 기능
    - Z좌표와 관계없이 렌더링 순서를 제어 할 수 있음
  • Sort Order
    - 렌더링 되는 순서를 수치로 설정


World Space 모드 

  • 설정된 Canvas는 씬에 있는 다른 게임 오브젝트와 동일한 자격으로 취급
  • Canvas의 크기는 Rect Transform 컴포넌트에 따라 정의
  • UI 요소는 씬에 있는 다른 GameObject와 함께 3D 공간에서의 위치 관계대로 렌더링 됨
  • UI요소를 씬의 일부로 다룰 때 이용하면 좋음
  • Event Camera
    - 이벤트를 처리하기 위한 카메라를 지정
    - OnClickButton()과 같은 UI 이벤트 리스너를 통해 발생 되는 결과가 적용될 대상
  • Sorting Layer
    - 캔버스의 소팅 레이어(Sorting Layer)를 지정.
  • Sort Order
    - 렌더링 되는 순서를 수치로 설정





2019년 9월 4일 수요일

Unity 비동기 로딩(LoadLevelAsync) 일시 정지(Pause)

유니티의 백그라운드에서 비동기적으로 레벨을 로드하는 동안 로딩바를 표시하는 기능과 로딩 완료 시 Play 버튼이 발생해 다른 Scene로 전환되는 기능에 대한 요약 정리



예제

  1. 더미 값을 통해 로딩이 진행 되는 과정 표시
  2. 씬 로딩 완료 후 Start 버튼 표시
  3. 버튼 선택 시 지정된 Scene로 이동

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;  // 씬 이동 처리를 위한 선언
using UnityEngine.UI;               // 게이지 이동 처리를 위한 선언

public class LoadLevelAsyncCode : MonoBehaviour
{
    // 화면에 표시되는 LoadingBar 리소스 연결
    public Slider sliderUI;
    // 화면에 표시되는 toPlay 버튼 리소스 연결
    public GameObject toPlayButtonUI;

    // 더미 시간의 설정 Min Max 값
    float dummyTimeRange_Min;
    float dummyTimeRange_Max;

    // 최초 게이지가 증가되는 더미 시간 -> 이후 본 로딩 시작
    float dummyTime;

    // 로딩 이후 시작 버튼 처리 
    bool toPlayButton;

    void Awake()
    {
        dummyTimeRange_Min = 0.8f;
        dummyTimeRange_Max = 1.5f;
        dummyTime = 0;

        // 버튼의 상태를 초기화 한다.
        toPlayButton = false;
    }

    void Start()
    {
        // UI를 처리 한다.
        sliderUI.gameObject.SetActive(true);
        toPlayButtonUI.SetActive(false);

        // 로딩을 즉시 실행
        StartCoroutine(LoadAsynchronously(1));
    }

    IEnumerator LoadAsynchronously(int _sceneIndex)
    {
        // 더미 타이머로 진행할 값을 설정
        dummyTime = Random.Range(dummyTimeRange_Min, dummyTimeRange_Max);

        // 게이지로 표현되는 loading 값 변수들
        float loadingTime = 0.0f;   // 시간 계산 용
        float progress = 0.0f;      // 게이지 용


        // 타이머 게이지 처리 
        while (loadingTime <= dummyTime)
        {
            // 프레임 당 시간을 증가 
            loadingTime += Time.deltaTime;

            // AsyncOperation 를 통한 추가 로딩 처리를 위해 0.9 값 을 백분율화 
            // 이후 opertaion.progress 는 0.9 까치 처리 되고 완료 된다.
            progress = Mathf.Clamp01(loadingTime / (0.9f + dummyTime));

            // 슬라이더바의 값 증가 처리
            sliderUI.value = progress;
            
            yield return null;
        }

        // "AsyncOperation"라는 "비동기적인 연산을 위한 코루틴을 제공"
        AsyncOperation operation = SceneManager.LoadSceneAsync(_sceneIndex);

        // 로딩 후 스타트 버튼 처리를 위한 선언
        // 이 항목이 없으면 바로 로딩 후 Scene 이동이 처리 됨
        operation.allowSceneActivation = false;

        // 로딩이 종료되기 전까지의 로딩창 게이지 처리
        while (!operation.isDone)
        {
            // 비동기 로딩 진행에 따른 게이지 처리
            progress = Mathf.Clamp01((operation.progress + loadingTime) / (0.9f + dummyTime));

            // 슬라이더 증가 처리
            sliderUI.value = progress;

            yield return null;

            // 로딩 이후의 처리 , 버튼을 누르면 씬 이동이 처리 된다.
            // UI를 반전 처리 한다.
            //sliderUI.gameObject.SetActive(false);
            toPlayButtonUI.SetActive(true);
            Debug.Log("toPlayButtonUI.SetActive(true) - Line");
            // toPlayButton 입력을 대기 한다.
            if (toPlayButton)
            {
                operation.allowSceneActivation = true;
            }

            yield return null;

        }
               
    }

    // 버튼을 입력 한다.
    public void ToPlayButton()
    {
        toPlayButton = true;
    }

}

2019년 6월 26일 수요일

Unity에서 Logcat 정보 보기

안드로이드 개발 중 디버깅 시 Log 를 볼 수 있는 장소가 Android Studio의 Logcat 창이다.
이 창에서는 기기에서 오류와 (앱에서 Log 클래스로 작성한) 메시지들을 볼 수 있다.
(Andriod SDK 설치 폴더 내 tools/monitor.bat 로 연결된 기기와 Logcat 확인 가능)

하지만 Unity와 Android Studio을 실행해 Logcat 창을 확인하는 것 보다 Unity에서 바로 Logcat에 표시되는 정보를 확인할 수 있는 방법이 있다.

Logcat (android logging) extension for Unity3D
Link : https://github.com/dzonatan/Unity3D-LogCat-extension

Link 내 How to use 정보와 같이
Asset>Editor 폴더를 생성해 LogCatWindow.cs를 위치 시키고, Unit 메뉴의 Window>LogCat - Android Logger 을 선택하면 Logcat 윈도우를 띄울 수 있다. 




















Debug.Log확인 및 AdMob에서 사용할 테스트 기기 번호를 확인하는 데 사용 했다.

Unity "Build And Run" 미 실행 오류

유니티에 기기를 연결해두고 기기에서 게임을 삭제해 가며 Build And Run 으로 게임을 테스트 하다 보면 종종 "Build completed with a result of 'Succeeded'"으로 성공 메시지가 표시되지만, 기기에서는 실행이 되지 않는 경우가 있다.

이런 문제가 종종 발생한 기기는 구글 계정이 복수로 등록된 기기였다.

기기의 옵션 메뉴에서 설치된 전체 App 리스트를 확인해 테스트를 한 게임 앱이 정상적으로 삭제되었는지 확인하고, 삭제되지 않았으면 우측 상단 메뉴>"모든 사용자에 대해 제거"로 다시 삭제하면 정상적으로 Build And Run 기능이 동작하게 된다.

Unity Build And Run "CommandInvokationFailure: Unable to install APK to device. Please ...." 오류

유니티에서 Build And Run을 실행하는 중에 다음과 같은 에러가 발생 될 수 있다.

CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.
...
[INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.kkumgames.Sample_Gpgs_ADMob signatures do not match the previously installed version; ignoring!]
...

기기 또는 에뮬레이터에서 현재 빌드하는 게임과 동일한 패키지명을 가진 게임이 설치되어 있어서 발생한다.

따라서 설치된 게임을 삭제 후 재시도 하면 된다.

2019년 6월 25일 화요일

Unity PlayerSettings의 Version 참조

유니티의 PlayerSettings > Other Settings > Version 에 입력된 값을 출력하는 스크립트.
PlayerSettings.bundleVersion 는 에디터 전용이라 Apk로 Build 시 사용 할 수는 없음.

using UnityEngine;
using UnityEngine.UI;

using UnityEditor;

public class MyVersion : MonoBehaviour
{
    public Text versionText;

    void Start()
    {
        // using UnityEditor; 와 세트로 edit 전용
        //buildVersionText.text = "Version - " + PlayerSettings.bundleVersion;

        // 빌드 시 사용 할 수 있음
        buildVersionText.text = "Version - " + Application.version;
    }
}

'다른 사용자가 이 기기에 호환되지 않는 버전을....' 오류

기기에 앱을 설치 및 업데이트해 가며 테스트하는 중 때때로 다음과 같은 오류 문구가 발생한다.

'다른 사용자가 이 기기에 호환되지 않는 버전을 설치했기 때문에 이 앱을 설치할 수 없습니다.'


이는 기기에 2개 이상의 구글 계정이 등록되어, 계정 중 한 곳에서 앱이 정상적으로 삭제되지 않아 발생 된다.

이를 다음과 같이 해결할 수 있다.

1. [설정] > [앱 및 알림] > [설치한 앱] > 앱 정보로 이동
2. 이후 우측 상단 메뉴의 "모든 사용자에 대해 제거"를 선택해 삭제
3. 이후 테스트 앱 재설치 시도

Unity GPGS LeaderBoard "Play 게임에 문제가..." 오류

유니티에 GPGS 플러그인을 이용해 Leaderboard 작업중 발생 하는 오류.

"Play 게임에 문제가 발생했습니다."





















개인적인 경험으로 테스트를 안드로이드 emulator 또는 Nox와 같은 앱플레이어에서 할 경우 잘 발생 했다.

이런 오류는 앱 설치 후 리더보드를 보는 기능까지는 문제가 없지만 LeaderBoard에 점수를 입력하는 경우, 위와 같은 에러와 함께 이후 LeaderBoard와 관련된 어떤 작업도 할 수 없게 된다.


이럴 경우 다음과 같이 해결 했다.

1. Google Console에 다음 버전의 APK 를 업로드 하여 출시
2. 기기에 기존 버전의 앱 삭제
2. Google Play에서 앱을 다운 받아서 재 설치 후 테스트


Unity GPGS LeaderBoard 정보 획득 및 가공

유니티에서 구글 리더보드에 등록되어 있는 내 점수를 획득 하는 방법

using UnityEngine;
using GooglePlayGames;
using UnityEngine.SocialPlatforms;

public class GPGSIntegration : MonoBehaviour
{
    long bestScore;

    void GetLeaderBoardScore()
    {
        ILeaderboard lb = PlayGamesPlatform.Instance.CreateLeaderboard();
        // GPGS에서 생성한 GPGSIds 클래스 리더보드 변수명
        lb.id = GPGSIds.leaderboard_bestscore;

        lb.LoadScores(scores =>
        {
            bestScore = lb.localUserScore.value;
        });
    }
}


그리고 리더보드의 정보를 획득해 다음과 같이 가공할 수 있다.

using UnityEngine;
using GooglePlayGames;
using UnityEngine.SocialPlatforms;

public class GPGSIntegration : MonoBehaviour
{
    long bestScore;

    void ShowLeaderBoardMyInfo()
    {
        ILeaderboard lb = PlayGamesPlatform.Instance.CreateLeaderboard();
        // GPGS에서 생성한 GPGSIds 클래스 리더보드 변수명
        lb.id = GPGSIds.leaderboard_bestscore;

        lb.userScope = UserScope.Global;
        lb.range = new Range(1,10);
        lb.timeScope = TimeScope.AllTime;

        lb.LoadScores(scores =>
        {
            uint all_player = lb.maxRange;
            int my_rank = lb.localUserScore.rank;
            decimal percent = (decimal)my_rank / (decimal)all_player;

            text.text = scores.ToString() + "\nAllPlayer: " + all_player + "\nMyRank: " + my_rank + "\nMyScore: " +lb.localUserScore.value.ToString() + "\nPercent: " + percent + "%";
        });    
    }
}
출력 정보








출처 : https://stackoverflow.com/questions/55234701/google-play-games-leaderboard-custom

2019년 6월 21일 금요일

Unity - Job failed with exception: GooglePlayServices.JavaUtilities+ToolNotFoundException: jar not found Error

유니티 프로젝트에 GooglePlayGamesPlugin-0.9.64.unitypackage Import 후 아래 에러가 발생 될 경우의 처리.

Job failed with exception: GooglePlayServices.JavaUtilities+ToolNotFoundException: jar not found....

으로 시작 하는 에러가 발생 되는 경우가 있음.

이는 Unity 의 Edit>Preferences>External Tools 의 JDK 경로 설정이 정상적이지 않아서 발생 될 수 있으므로, 이를 재 설정해 줌.

1. "Use Embedded JDK" 체크를 해제
2. JDK 경로 확인 ( C:\Program Files\Unity\Editor\2018.3.14f1\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\OpenJDK\Windows )
3. "Use Embedded JDK" 체크를 다시 설정
4. 유니티 재 실행

이와 같이 JDK의 경로를 수동으로 재 설정해 주면 에러가 사라질 수 있음.

2019년 6월 19일 수요일

Particle System에서 설정하는 Start Color 을 Script 로 변경

Particle Prefab 의 Particle System에서 설정하는 Start Color 을 Script 로 변경
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Fxlab : MonoBehaviour
{
    public GameObject fxPrefab;
    public Color fxColor;

    void start()
    {
        FXPrefab.GetComponent().main.startColor = fxColor;    
    }
}
이와 같이 선언 하면 FXPrefab.GetComponent().main 이 get 으로 수정을 할 수 없다.


이럴때는 아래와 같이 선언하여 Particle 의 Start Color를 수정 할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Fxlab : MonoBehaviour
{
    public GameObject fxPrefab;
    public Color fxColor;

    void start()
    {
        ParticleSystem currentParticleSystem = fxPrefab.GetComponent();
        ParticleSystem.MainModule psMain = currentParticleSystem.main;

        psMain.startColor = fxColor;
    }
}

2019년 6월 13일 목요일

Material.SetTexture 메터리얼 내 텍스트 변경

메터리얼 내 텍스쳐를 스크립트로 변경하는 메소드
(파티클 렌더러의 텍스쳐를 변경하는데도 사용 가능)

public void SetTexture(string name, Texture value);

name : 변경시키고자 하는 메터리얼 내 텍스쳐 변수명
value : 변경 하려는 텍스쳐 리소스

아래와 같이 설정해 사용할 수 있다.

using UnityEngine;
using System.Collections;

public class ChangeTexture : MonoBehaviour
{
    public Texture gameDataTex;

    public Material gameDataMat;

    public void ChangeShaderTexture()
    {
        gameDataMat.SetTexture("_MainTex", gameDataTex);
    }
}
gameDataMat 내 _MainTex 변수에 설정된 텍스쳐를 gameDataTex에 설정된 텍스쳐로 변경.

_MainTex 와 같은 타겟 정보는 해당 메터리얼(gameDataMat에 설정된 리소스)의 Inspector에서 확인할 수 있다.




2019년 5월 27일 월요일

Unity C# AES 암호화/복호화

유니티에서 C#에서 지원해주는 암호화 기능을 사용해 데이터를 숨기는 기능
로컬에 JSON 형식(string 형식)으로 데이터의 저장 시 정보를 숨기는데 적용이 가능
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;

public class AESCrypto : MonoBehaviour
{
    // 키로 사용하기 위한 암호 정의
    private static readonly string PASSWORD = "3ds1s334e4dcc7c4yz4554e732983h";

    // 인증키 정의
    private static readonly string KEY = PASSWORD.Substring(0, 128 / 8);

    // 암호화
    public static string AESEncrypt128(string plain)
    {
        byte[] plainBytes = Encoding.UTF8.GetBytes(plain);

        RijndaelManaged myRijndael = new RijndaelManaged();
        myRijndael.Mode = CipherMode.CBC;
        myRijndael.Padding = PaddingMode.PKCS7;
        myRijndael.KeySize = 128;

        MemoryStream memoryStream = new MemoryStream();

        ICryptoTransform encryptor = myRijndael.CreateEncryptor(Encoding.UTF8.GetBytes(KEY), Encoding.UTF8.GetBytes(KEY));

        CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
        cryptoStream.Write(plainBytes, 0, plainBytes.Length);
        cryptoStream.FlushFinalBlock();

        byte[] encryptBytes = memoryStream.ToArray();

        string encryptString = Convert.ToBase64String(encryptBytes);

        cryptoStream.Close();
        memoryStream.Close();

        return encryptString;
    }

    // 복호화
    public static string AESDecrypt128(string encrypt)
    {
        byte[] encryptBytes = Convert.FromBase64String(encrypt);

        RijndaelManaged myRijndael = new RijndaelManaged();
        myRijndael.Mode = CipherMode.CBC;
        myRijndael.Padding = PaddingMode.PKCS7;
        myRijndael.KeySize = 128;

        MemoryStream memoryStream = new MemoryStream(encryptBytes);

        ICryptoTransform decryptor = myRijndael.CreateDecryptor(Encoding.UTF8.GetBytes(KEY), Encoding.UTF8.GetBytes(KEY));

        CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);

        byte[] plainBytes = new byte[encryptBytes.Length];

        int plainCount = cryptoStream.Read(plainBytes, 0, plainBytes.Length);

        string plainString = Encoding.UTF8.GetString(plainBytes, 0, plainCount);

        cryptoStream.Close();
        memoryStream.Close();

        return plainString;
    }

    // 적용 예제
    void Start()
    {
        string str = "원본 문자 정보";
        Debug.Log("plain : " + str1);

        string str1 = AESEncrypt128(str1);
        Debug.Log("AES128 encrypted : " + str1);

        string str2 = AESDecrypt128(str2);
        Debug.Log("AES128 decrypted : " + str2);
    }
}

2019년 5월 17일 금요일

Unity에서 List 의 FindAll() 을 이용한 데이터 취합

Unity에서 List의 FinaAll()을 이용해 데이터를 취합하는 방법이다.
List에 저장되어 있는 데이터를 이용해 취합하려는 조건을 설정 할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NumGroup
{
    public int     index;
    public string  name;

    public NumGroup(int index, string name)
    {
        this.index = index;
        this.name = name;
    }
}

public class LinqExample : MonoBehaviour
{
    List numbersA = new List();
    List numbersB = new List();

    List numGroupA = new List();
    List numGroupB = new List();

    void Start()
    {
        // numbersA : 1,2,5,8
        numbersA.Add(1);
        numbersA.Add(2);
        numbersA.Add(5);
        numbersA.Add(8);

        // numbersB : 1,3,5,7,9
        numbersB.Add(1);
        numbersB.Add(3);
        numbersB.Add(5);
        numbersB.Add(7);
        numbersB.Add(9);

        // FindAll 메서드
        // list 에 저장되어 있는 int 값 n 을 이용해 n % 2 == 0 연산이 옳으면 저장 한다.
        List findallA = numbersA.FindAll(n => n % 2 == 0);
        // 결과 : 2, 8

        // FindAll 메서드
        // list 에 저장되어 있는 int 값 n 을 이용해 n != numbersB[0] 연산이 옳으면 저장 한다.
        List findallB = numbersA.FindAll(n => n != numbersB[0]);
        // 결과 : 2, 5, 8


        ///
        /// class 형식의 데이터 연산
        ///
        
        // numbersA : 1 "가나다" , 2 "마바사" , 5 "아자차" , 8 "파타하"
        numGroupA.Add(new NumGroup(1, "가나다"));
        numGroupA.Add(new NumGroup(2, "마바사"));
        numGroupA.Add(new NumGroup(5, "아자차"));
        numGroupA.Add(new NumGroup(6, "파타하"));

        // numbersB : 1 "AAA" , 3 "BBB" , 5 "CCC" , 7 "DDD" , 9 "EEE"
        numGroupB.Add(new NumGroup(1, "AAA"));
        numGroupB.Add(new NumGroup(3, "BBB"));
        numGroupB.Add(new NumGroup(5, "CCC"));
        numGroupB.Add(new NumGroup(7, "DDD"));
        numGroupB.Add(new NumGroup(9, "EEE"));

        // FindAll 메서드
        // list 에 저장되어 있는 NumGroup 클래스 n(numGroupA) 을 이용해 n.index % 2 == 0 연산이 옳으면 저장 한다. 
        List findallGroupA = numGroupA.FindAll(n => n.index % 2 == 0);
        // 결과 : 2 "마바사" , 8 "파타하"
        
        // FindAll 메서드
        // list 에 저장되어 있는 NumGroup 클래스 n(numGroupA) 을 이용해 n.index != numGroupB[0].index 연산이 옳으면 저장 한다. 
        List findallGroupB = numGroupA.FindAll(n => n.index == numGroupB[0].index);
        // 결과 : 1 "가나다"


        // FindAll 메서드
        List findallGroupC = new List();

        // List의 AddRange()는 한번에 다수의 데이터(데이터 목록)를 추가 할 수 있다. (IEnumerable 인터페스를 구현한 컬렉션 객체의 추가가 가능하다.)
        // list 에 저장되어 있는 NumGroup 클래스 n(numGroupA) 을 이용해 n.index != numGroupB[i].index 연산이 옳으면 더한다.
        for (int i = 0; i < numGroupB.Count; i++)
        {
            findallGroupC.AddRange(numGroupA.FindAll(n => n.index == numGroupB[i].index));
        }
        // 결과 : 1 "가나다" , 5 "아자차"

    }
}

Unity에서 LINQ를 이용한 List 연산

Unity에서 Linq를 이용해 List를 연산하는 방법이다.
LINQ란 자주 사용 되는 정보의 선택/열거 작업을 다루기 위한 기존 문법의 확장이다.
사용법은 SQL 쿼리구문과 유사하다.

Unity서 List로 관리되는 데이터는 LINQ의 문법으로 연산이 가능 하다.
LINQ로 교집합, 차집합, 합집합 연산을 아래와 같이 간단히 할 수 있다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Linq를 사용 한다고 선언
using System.Linq;

public class LinqExample : MonoBehaviour
{
    List numbersA = new List();
    List numbersB = new List();
    
    void Start()
    {
        // numbersA : 1,2,5,8
        numbersA.Add(1);
        numbersA.Add(2);
        numbersA.Add(5);
        numbersA.Add(8);

        // numbersB : 1,3,5,7,9
        numbersB.Add(1);
        numbersB.Add(3);
        numbersB.Add(5);
        numbersB.Add(7);
        numbersB.Add(9);

        // 차집합 : numbersA 에서 numbersB가 중복되면 제외 한다. 
        // 결과 : 2, 8
        List except = numbersA.Except(numbersB).ToList();

        // 교집합 : numbersA 에서 numbersB가 중복되면 저장 한다.
        // 결과 : 1, 5
        List intersect = numbersA.Intersect(numbersB).ToList();

        // 합집합 : numbersA 와 numbersB를 중복을 하나로 처리 하여 모두 저장한다.
        // 결과 : 1, 2, 5, 8, 3, 7, 9
        List union = numbersA.Union(numbersB).ToList();
    }
}

2019년 5월 14일 화요일

Unity Console 창 메시지 삭제 함수

DebugInfo 메서드 실행 시 Unity의 Console Window 의 메시지 들을 삭제한 뒤 Debug.Log() 처리가 이루어 진다.

using System.Reflection;

public void DebugInfo()
{
    var assembly = Assembly.GetAssembly(typeof(UnityEditor.Editor));
    var type = assembly.GetType("UnityEditor.LogEntries");
    var method = type.GetMethod("Clear");
    method.Invoke(new object(), null);

    Debug.Log("Debug Message");
}

2019년 5월 13일 월요일

unity GameObject의 모든 자식 GameObject들을 삭제 하기

현재 GameObject의 자식으로 등록된 GameObject를 모두 삭제 하는 메서드이다.

public void DeleteChilds()
{
    // child 에는 부모와 자식이 함께 설정 된다.
    var child = this.GetComponentsInChildren();

    foreach (var iter in child)
    {
        // 부모(this.gameObject)는 삭제 하지 않기 위한 처리
        if(iter != this.transform)
        {
            Destroy(iter.gameObject);
        }
    }
}

Unity Generics Singleton을 이용한 Manager 생성

Generics 타입의 Singleton 패턴을 이용해 DataManager 클래스를 생성한다.
그리고 생성한 DataManager 클래스의 변수 및 메서드는 어느 클래스에서도 접근할 수 있다.

Generics 타입으로 Singleton을 상속받아 재활용할 수 있다.
Awake() 메서드를 통해 Singleton에 맞게 GameObject가 중복으로 생성되지 않도록 처리되며,
Manager로 사용하기 위해, Scene 이동 시 삭제되지 않도록 처리되었다.

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

public class Singleton : MonoBehaviour where T : MonoBehaviour
{
    // Singleton Instance 선언
    static T m_instance;

    // Singleton Instance에 접근하기 위한 프로퍼티
    public static T Instance
    {
        get
        {
            if (m_instance == null)
            {
                // T 라는 오브젝트의 형(컴포넌트의 형)을 검색해 가장 처음 오브젝트를 반환 한다.
                m_instance = GameObject.FindObjectOfType();

                // instance 가 없을 경우 GameObject를 생성해 선언한다.
                if (m_instance == null)
                {
                    // T 컴포넌트 의 이름으로 생성 한다.
                    GameObject singleton = new GameObject(typeof(T).Name);
                    m_instance = singleton.AddComponent();
                }
            }

            return m_instance;
        }
    }

    public virtual void Awake()
    {
        if (m_instance == null)
        {
            m_instance = this as T;
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

// Singleton 의 파생으로 Manager 클래스 생성
public class DataManager : Singleton
{
    // Manager 클래스용 데이터 설정
    public bool isWrite = false;
    public int itemCount = 0;

    // DataManager에서 Awake 메서드 사용 시 선언
    public override void Awake()
    {
        base.Awake();
    }
}

public class DataUpdate
{
    void SetItem()
    {
        // DataManager 클래스에 접근이 가능 하다.
        DataManager.Instance.itemCount = 10;
    }
}

Unity Singleton을 이용한 Manager 생성

Singleton 패턴을 이용해 GameManager 클래스를 생성한다.
그리고 생성한 GamaManager 클래스의 변수 및 메서드는 어느 클래스에서도 접근할 수 있다.

Awake() 메서드를 통해 Singleton에 맞게 GameObject가 중복 생성되지 않도록 처리되며,
Manager로 사용하기 위해, Scene 이동 시 삭제되지 않도록 처리되었다.

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

public class GameManager : MonoBehaviour
{
    //  Singleton Instance 선언
    private static GameManager instance = null;

    // Singleton Instance에 접근하기 위한 프로퍼티
    public static GameManager Instance
    {
        get
        {
            return instance;
        }
    }

    // GameManager 에서 사용 하는 데이터
    public bool isPause = false;
    public int score = 0;

    void Awake()
    {
        // Scene에 이미 인스턴스가 존재 하는지 확인 후 처리
        if(instance)
        {
            Destroy(this.gameObject);
            return;
        }

        // instance를 유일 오브젝트로 만든다
        instance = this;

        // Scene 이동 시 삭제 되지 않도록 처리
        DontDestroyOnLoad(this.gameObject);
    }
}

public class GameContorl
{
    public void IsPause()
    {
        GameManager.Instance.isPause = true;
    }
}

Unity - Firebase 연동 (Analytics, AdMob)

버전 : firebase_unity_sdk_6.5.0.zip 게임에서 통계 측정 및 광고 추적을 위해 Firebase 을 연동한다. 앞서 [Unity - GPGS 와 Admob 연동 및 배포 준비 작업]  연동 이후에 작업을 진행 한다. 유니...