2015년 4월 20일 월요일

Unity3d 네트워크 상태 판단

유니티 함수로 네트워크 상태를 판단하려면 Application.internetReachability을 사용하여 알 수 있다.


Application.internetReachability

public static NetworkReachability internetReachability;

Description

Returns the type of Internet reachability currently possible on the device.
This property is mostly useful on handhelds to distinguish fast and cheap WiFi connection from carrier networking.

Note: Do not use this property to determine the actual connectivity. E.g. the device can be connected to a hot spot, but not have the actual route to the network. Non-handhelds are considered to always be capable of NetworkReachability.ReachableViaLocalAreaNetwork.
실제 연결을 확인하려면이 속성을 사용하지 마세요. 예를들면 device는 hot spot에 접속하지만, 실제의 네트워크 경로를 가질 수 없습니다.. Non-handhelds는 항상 NetworkReachability.Reachable 통해 LocalAreaNetwork를 할 수 있다고 간주합니다.
(http://docs.unity3d.com/ScriptReference/Application-internetReachability.html)

실제 서비스한 프로젝트에서 위 유틸을 사용했지만 많은 시행 착오 및 신뢰성이 떨어졌었다.

하여 가능하면 단말기 자체의 네트워크 상태정보를 가져오는것이 더 신뢰성이 높으므로
Navite코드를 통하여 Device의 상태정보를 가져올 수 있어야한다.

* AOS Native 관련 포스트
http://developer.android.com/training/basics/network-ops/managing.html
http://mainia.tistory.com/549

* IOS Native 관련 포스트
http://reysion.tistory.com/48

2015년 4월 19일 일요일

동기부여의 과학




금전적인 인센티브라는것은 어쩌면 원시시대로부터 내려오던 동기부여 제도인것 같다.
"더 많은 일(성과)을 하면 더 많은 보상을 하겠다."
가장 직관적이고 명확한 보상체계인지 모른다.

하지만 오늘날의 사람들은 오로지 밥만을 위해 일하지 않는다.
Need Hierarchy Theory

상위 욕구
 
 
하위 욕구
자기실현 욕구
(Self-Actualization Needs)
존경 욕구
(Esteem Needs)
소속 및 애정 욕구
(Belongingness and Love Needs)
안전 욕구
(Safety Needs)
생리적 욕구
(Physiological Needs)

이미 소속 및 애정욕구가 채워진 사람들에게서는 금전적인 인센티브보다
내가 지금 하려하는 일이 본인에게 갖는 의미 때문에 일하기 때문이다.

그러기에 동영상의 Autonomy,Mastery,Purpose (자주, 숙달, 소명욕)이
동기부여를 한다는 말이 과학적으로나 현실적으로 맞는말이라고 생각한다.

나 조차도 자주적이고 내스스로 발전할 수 있으며 다른사람을 위해 기여할 수 있는일을 하고 싶다.

물론, 나같은 보통사람은 당장 내일 먹을 밥이 걱정된다면 위와같은 말은 허상이 되겠지만,,




2015년 4월 15일 수요일

Unity3D에서 Native 함수 호출

AOS
private AndroidJavaClass unityPlayerClass;
private AndroidJavaObject unityPlayerActivity;

void Awake()
{
    unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    unityPlayerActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
}
  • "currentActivity"로 접근해서 얻는 이유.
    Call 함수의 엔진 내부 동작은 달빅VM 쓰레드에 연결된 jnienv의 포인터를 받은 후 GetMethodID 함수를 통해 스트링으로 제공하는 함수 이름에 맞는 함수의 ID를 찾아 실행시켜 줍니다.
    매번 GetMethodID를 호출하여 ID를 찾으면 시간이 걸리니 엔진 내부에서는 캐싱 테이블로 빠르게 ID를 찾을 수 있게 제공합니다.
    따라서 Call 함수를 부모 클래스의 레퍼런스상에서 호출하더라도 C#의 Reflection 처럼 동작하여 문제 없이 EclipseBasicActivity의 함수를 호출할 수 있게 됩니다.
    http://unitystudy.net/bbs/board.php?bo_table=qanda&wr_id=174
  • Destroy할때 Dispose 해주자.
    void OnDestroy()
    {
        if (unityPlayerActivity != null)
        {
           unityPlayerActivity.Dispose();
           unityPlayerActivity = null;
        }
    
        if (unityPlayerClass != null)
        {
            unityPlayerClass.Dispose();
            unityPlayerClass = null;
        }
    }
    
  • Native 메소드 호출 방법
    // (void func0())
    unityPlayerActivity.Call("func0");
    // (void func1(string msg))
    unityPlayerActivity.Call("func1", "message");
    // (void func2(int val))
    unityPlayerActivity.Call("func2", value);
    // (bool func3())
    boo bRet = unityPlayerActivity.Call<bool>("func3");
    

IOS
using System.Runtime.InteropServices; // 선언

[DllImport("__Internal")]
private static extern void func1();

[DllImport("__Internal")]
private static extern int func2();
  • 다른 플러그인 시스템과 마찬가지로 C#과 네이티브 코드는 다른 영역이며, C#에서 네이티브를 호출할 때에는 .NET의 PInvoke 기능을 사용하고, 네이티브에서는 유니티 라이브러리에서 제공하는 UnitySendMessage를 사용하여 C#의 함수를 호출합니다.
    PInvoke를 사용하기 위해서는 System.Runtime.InteropServices 네임스페이스를 사용해야하며, [DllImport(“__Internal”)] 프로퍼티를 C#의 static 멤버 함수에 설정하면 Objective C 코드에서 선언된 함수와 일치하게 됩니다.
    이 때 Objective C 코드의 함수는 C 스타일로 정의되어야 하며, 이를 위해 함수에 extern “C”키워드를 명시적으로 주어 name mangling 문제가 일어나지 않도록 합니다.
    http://www.unitystudy.net/bbs/board.php?bo_table=dustin&wr_id=402 // [모바일] iOS 플러그인 제작


ICSharpCode.SharpZipLib의 사용

ICSharpCode.SharpZipLib.dll의 Unzip (MemoryStream)
byte[] zipData = new byte[1024];
using (GZipInputStream gzs = new GZipInputStream(new MemoryStream(zipData)))
{
    using (MemoryStream ms = new MemoryStream())
    {
        const int count = 4096;
        byte[] dest = new byte[count];
        for (int length = 0; (length = gzs.Read(dest, 0, count)) > 0; )
            ms.Write(dest, 0, length);
        zipData = ms.ToArray();
    }
}
Unity에 사용한 간단한 unzip 라이브러리, ICSharpCode.SharpZipLib

복수의 파일을 압축하거나 풀수도 있고 다양한 형식을 지원한다.
AssetBundle을 압축하거나 패킷을 압축하는데 활용함.

패킷의 경우 보통 Web에서는 Json위주로 통신하지만 String이다보니 패킷양이 많아지는 경향이 있다.
하여 Json자체를 압축하여 사용하면 패킷통신양을 줄일 수 있다.

출처 : 





JsonFX 사용 예 (C#)

using UnityEngine;
using System.Collections;

public static class cJson
{
    public static string Serialize(object obj)
    {
        return JsonFx.Json.JsonWriter.Serialize(obj);
    }

    public static T Deserialize<T>(string str) where T : class
    {
        if (str == null || str == "") return null;

        try
        {
            return JsonFx.Json.JsonReader.Deserialize<T>(str);
        }
        catch (System.Exception e)
        {
            Debug.LogError(e.Message);
            return null;
        }
    }
}
JsonFX의 기본 사용 법

Serialize가 필요한 Class를 매개변수로 넣어 Json형식의 string으로 받음.
Deserialize시 얻어낼 Class를 제네릭으로 받아 Json형식의 string을 매개변수로 넣어 Class 형태로 얻어낸다.

공식사이트는 www.jsonfx.net 이지만, 다운로드 링크가 깨져있음.
dll 다운로드(version 1.4.x) >>JsonFx.Json.dll


2015년 4월 14일 화요일

Rijndael 알고리즘을 이용한 암호화 예제 C#

  • 암호화 모듈
    https://msdn.microsoft.com/ko-kr/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
    using System.Security.Cryptography;
    
    private static readonly int KEYSIZE = 128;
    private static readonly int BLOCKSIZE = 128;
    
    private readonly RijndaelManaged rijndael = new RijndaelManaged();
    
    rijndael.Mode = CipherMode.CBC;
    rijndael.Padding = PaddingMode.PKCS7;
    rijndael.KeySize = KEYSIZE;
    rijndael.BlockSize = BLOCKSIZE;
    
    // 복호화
    public byte[] decrypt(byte[] inputBuffer)
    {
        return rijndael.CreateDecryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
    }
    // 암호화
    public byte[] encrypt(byte[] inputBuffer)
    {
         return rijndael.CreateEncryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
    }
Rijndael 알고리즘을 이용한 암호화 처리.

byte[]로 되어 있는 rijndael.Key, rijndael.IV를 키로 사용하여 암호화, 복호화를 진행한다.