출처 : http://tech031.blogspot.kr/2015/08/unity.html





레이캐스트 메서드를 사용할 때 특정 레이어를 인자값으로 넘겨서 그 레이어만 충돌체크 할 수 있다.
사용 예는 아래와 같다.

RaycastHit 충돌을 받아올 변수; 
Physics.Raycast (Vector3 레이의 시작점 백터, Vector3 레이의 방향백터, RaycastHit 충돌을 받아올 변수, float 탐지거리, int 레이어마스크); 

레이어마스크는 비트 값을 이용하므로 정수 1에 쉬프트연산자를 사용해서
원하는 레이어의 비트 값을 얻어낼 수 있다.
예를 들어 레이어이름이 Stuck이라는 레이어의 비트마스크를 얻으려면

int layerMask = 1<<LayerMask.NameToLayer("Stuck");  

문제는 복수의 레이어를 상대로 레이캐스팅을 해야할 때 인자값으로 넘겨줄 레이어마스크 값은 하나만 지정해줄 수 있는 것이 문제. 
이 때는 OR연산자( | )를 이용해서 복수의 레이어를 하나의 비트마스크 값으로 만들어낼 수 있다. 
아래의 예는 1번 레이어와 2번 레이어의 정보를 담는 레이어마스크 값을 만들어낸다.

int layermask = (1<<LayerMask.NameToLayer(“1번 레이어이름”) | (1<<LayerMask.NameToLayer(“5번 레이어이름”); 


다른 경우로 전체 레이어중에서 특정 레이어만 제외하고자 하는 값을 만들어내고자 한다면 아래와 같이 해주면 된다.
아래의 예는 전체 레이어마스크에서 10번 레이어와 11번 레이어를  제외하는 정보를 담는 값을 만들어낸다.
두 코드는 같은 결과를 보여준다.

방법 1
int layerMask = (-1) - ((1 << LayerMask.NameToLayer("10번레이어이름")) | (1 << LayerMask.NameToLayer("11번레이어이름"))); 

방법 2
int layerMask = (1 << LayerMask.NameToLayer("10번레이어이름")) | (1 << LayerMask.NameToLayer("11번레이어이름"));
layerMask = ~layerMask // 비트연산자(Not) 

이렇게 만들어진 값을 레이캐스트 메서드의 인자 값으로 넘겨주면 해당 레이어의 오브젝트만 충돌검사를 수행한다.




'Unity > 스크립트' 카테고리의 다른 글

직렬화의 이해  (0) 2016.03.24
Reactive Extension  (0) 2015.12.11
Swipe 판별  (0) 2015.07.20
Android 국가코드 정보  (0) 2015.06.07
에셋 Android Native Plugins에 대해  (0) 2015.03.02

WRITTEN BY
빨강꼬마

,

Swipe 판별

Unity/스크립트 2015. 7. 20. 21:45

using UnityEngine;
using System.Collections;

public class Swipe : MonoBehaviour
{
    // const
    public const string RIGHT = "Right";
    public const string DOWN = "Down";
    public const string LEFT = "Left";
    public const string UP = "Up";
    // delegate
    public delegate void SwapeDelegate (string way);

    public SwapeDelegate swape {
        set {
            swapeDelegate = value;
        }
    }

    private SwapeDelegate swapeDelegate;
    // variable
    private Vector2 touchStartPos;
    private bool touchStarted;
    private float minSwipeDistancePixels = 100f;

    void Update ()
    {
        if (Input.touchCount > 0) {
            var touch = Input.touches [0];
            
            switch (touch.phase) {
            case TouchPhase.Began:
                touchStarted = true;
                touchStartPos = touch.position;
                break;
            case TouchPhase.Ended:
                if (touchStarted) {
                    Swipe (touch);
                    touchStarted = false;
                }
                break;
            case TouchPhase.Canceled:
                touchStarted = false;
                break;
            case TouchPhase.Stationary:
                break;
            case TouchPhase.Moved:
                break;
            }
        }
    }

    private void Swipe (Touch touch)
    {
        var lastPos = touch.position;
        var distance = Vector2.Distance (lastPostouchStartPos);
        
        if (distance > minSwipeDistancePixels) {
            float dy = lastPos.y - touchStartPos.y;
            float dx = lastPos.x - touchStartPos.x;
            
            float angle = Mathf.Rad2Deg * Mathf.Atan2 (dxdy);
            
            angle = (360 + angle - 45) % 360;

            if (angle < 90) {
                // right
                swapeDelegate ("Left");
            } else if (angle < 180) {
                // down
                swapeDelegate ("Down");
            } else if (angle < 270) {
                // left
                swapeDelegate ("Right");
            } else {
                // up
                swapeDelegate ("Up");
            }
        }
    }
}


출처 - http://seungngil.tistory.com/

'Unity > 스크립트' 카테고리의 다른 글

Reactive Extension  (0) 2015.12.11
Raycast시 원하는 충돌레이어 지정  (0) 2015.10.16
Android 국가코드 정보  (0) 2015.06.07
에셋 Android Native Plugins에 대해  (0) 2015.03.02
String -> enum 변환  (0) 2015.02.17

WRITTEN BY
빨강꼬마

,

private void getLocalesList(){

        Locale[] availableLocales = Locale.getAvailableLocales();

        for (Locale locale : availableLocales) {

            String iso = locale.getISO3Country();

            String code = locale.getCountry();

            String name = locale.getDisplayCountry();

            String lang = locale.getLanguage();

            Log.d("cjj", iso + ", " + code + ", " + name + ", " + lang);

        }


ANP로 한방에 끝!


ARE, AE, 아랍에미리트 연합, ar

BHR, BH, 바레인, ar

DZA, DZ, 알제리, ar

EGY, EG, 이집트, ar

IRQ, IQ, 이라크, ar

JOR, JO, 요르단, ar

KWT, KW, 쿠웨이트, ar

LBN, LB, 레바논, ar

LBY, LY, 리비아, ar

MAR, MA, 모로코, ar

OMN, OM, 오만, ar

QAT, QA, 카타르, ar

SAU, SA, 사우디아라비아, ar

SDN, SD, 수단, ar

SYR, SY, 시리아, ar

TUN, TN, 튀니지, ar

YEM, YE, 예멘, ar

BGR, BG, 불가리아, bg

ESP, ES, 스페인, ca

CZE, CZ, 체코, cs

DNK, DK, 덴마크, da

AUT, AT, 오스트리아, de

BEL, BE, 벨기에, de

CHE, CH, 스위스, de

DEU, DE, 독일, de

LIE, LI, 리히텐슈타인, de

LUX, LU, 룩셈부르크, de

GRC, GR, 그리스, el

AUS, AU, 오스트레일리아, en

BEL, BE, 벨기에, en

BWA, BW, 보츠와나, en

BLZ, BZ, 벨리즈, en

CAN, CA, 캐나다, en

GBR, GB, 영국, en

HKG, HK, 홍콩, 중국 특별행정구, en

IRL, IE, 아일랜드, en

IND, IN, 인도, en

JAM, JM, 자메이카, en

MHL, MH, 마샬 군도, en

MLT, MT, 몰타, en

NAM, NA, 나미비아, en

NZL, NZ, 뉴질랜드, en

PHL, PH, 필리핀, en

PAK, PK, 파키스탄, en

, RH, 짐바브웨, en

SGP, SG, 싱가포르, en

TTO, TT, 트리니다드 토바고, en

USA, US, 미국, en

USA, US, 미국, en

VIR, VI, 미국령 버진 아일랜드, en

ZAF, ZA, 남아프리카, en

ZWE, ZW, 짐바브웨, en

ARG, AR, 아르헨티나, es

BOL, BO, 볼리비아, es

CHL, CL, 칠레, es

COL, CO, 콜롬비아, es

CRI, CR, 코스타리카, es

DOM, DO, 도미니카 공화국, es

ECU, EC, 에콰도르, es

ESP, ES, 스페인, es

GTM, GT, 과테말라, es

HND, HN, 온두라스, es

MEX, MX, 멕시코, es

NIC, NI, 니카라과, es

PAN, PA, 파나마, es

PER, PE, 페루, es

PRI, PR, 푸에르토리코, es

PRY, PY, 파라과이, es

SLV, SV, 엘살바도르, es

USA, US, 미국, es

URY, UY, 우루과이, es

VEN, VE, 베네수엘라, es

AFG, AF, 아프가니스탄, fa

IRN, IR, 이란, fa

FIN, FI, 핀란드, fi

PHL, PH, 필리핀, fil

BEL, BE, 벨기에, fr

CAN, CA, 캐나다, fr

CHE, CH, 스위스, fr

FRA, FR, 프랑스, fr

LUX, LU, 룩셈부르크, fr

MCO, MC, 모나코, fr

ISR, IL, 이스라엘, iw

IND, IN, 인도, hi

HRV, HR, 크로아티아, hr

HUN, HU, 헝가리, hu

IDN, ID, 인도네시아, in

CHE, CH, 스위스, it

ITA, IT, 이탈리아, it

JPN, JP, 일본, ja

KOR, KR, 대한민국, ko

LTU, LT, 리투아니아, lt

LVA, LV, 라트비아, lv

NOR, NO, 노르웨이, nb

BEL, BE, 벨기에, nl

NLD, NL, 네덜란드, nl

POL, PL, 폴란드, pl

BRA, BR, 브라질, pt

PRT, PT, 포르투갈, pt

ROU, RO, 루마니아, ro

RUS, RU, 러시아, ru

UKR, UA, 우크라이나, ru

SVK, SK, 슬로바키아, sk

SVN, SI, 슬로베니아, sl

BIH, BA, 보스니아 헤르체고비나, sr

SCG, CS, 세르비아 및 몬테네그로, sr

BIH, CYRL, 보스니아 헤르체고비나, sr

SCG, CYRL, 세르비아 및 몬테네그로, sr

MNE, CYRL, 몬테네그로, sr

SRB, CYRL, 세르비아, sr

YUG, CYRL, 세르비아, sr

BIH, LATN, 보스니아 헤르체고비나, sr

SCG, LATN, 세르비아 및 몬테네그로, sr

MNE, LATN, 몬테네그로, sr

SRB, LATN, 세르비아, sr

YUG, LATN, 세르비아, sr

MNE, ME, 몬테네그로, sr

SRB, RS, 세르비아, sr

YUG, YU, 세르비아, sr

FIN, FI, 핀란드, sv

SWE, SE, 스웨덴, sv

THA, TH, 태국, th

TUR, TR, 터키, tr

UKR, UA, 우크라이나, uk

VNM, VN, 베트남, vi

CHN, CN, 중국, zh

HKG, HK, 홍콩, 중국 특별행정구, zh

CHN, HANS, 중국, zh

HKG, HANS, 홍콩, 중국 특별행정구, zh

SGP, HANS, 싱가포르, zh

HKG, HANT, 홍콩, 중국 특별행정구, zh

MAC, HANT, 마카오, 중국 특별행정구, zh

TWN, HANT, 대만, zh

MAC, MO, 마카오, 중국 특별행정구, zh

SGP, SG, 싱가포르, zh

TWN, TW, 대만, zh

'Unity > 스크립트' 카테고리의 다른 글

Raycast시 원하는 충돌레이어 지정  (0) 2015.10.16
Swipe 판별  (0) 2015.07.20
에셋 Android Native Plugins에 대해  (0) 2015.03.02
String -> enum 변환  (0) 2015.02.17
기본 변수 저장시 암호화  (0) 2014.10.16

WRITTEN BY
빨강꼬마

,

안드로이드는 폴더만 추가하여 넣어주면 자동으로 디바이스의 현재 설정 언어를 가져와서 해당하는 폴더의 string.xml을 자동으로 연결하여 보여 준다~

무슨 말인가 하면 안드로이드 프로젝트를 만들면 res 폴더 안에 아래와 같이 있을 겅미

 

 

 

아래에 보면 values 폴더가 하나 밖에 없는데 이 폴더를 이름을 좀 비슷하게 해서 생성해주면 자동으로 디바이스의 언어 설정을 가지고 그에 해당하는 문자열을 가져와서 보여 준다. 즉 아래 스샷은 세계공통(values), 영어(values-en), 일본어(values-ja), 한국어(values-ko), 중국어(values-zh)을 적용되게 만든 앱이다. 위에 선언된 4개국 언어 설정 외에는 다 '세계공통' 폴더 안에 있는 string.xml을 사용하게 된다

 

 

values-en 폴더의 strings.xml 파일입니다.

<string name="hello">Hello World, TestHHimLocationActivity!</string>
<string name="app_name">TestHHimLocation</string>


values-ko 폴더의 strings.xml 파일입니다.

<string name="hello">안녕하세요.!!!!</string>
<string name="app_name">Ko-한글입니다.</string>


언어 (국가)

폴더 이름

(언어)

폴더 이름

(언어 + 국가)

체코어 (체코)

values-cs

values-cs-rCZ

독일어 (독일)

values-de

values-de-rDE

독일어 (오스트리아)

values-de-rAT

독일어 (스위스)

values-de-rCH

독일어 (리히텐슈타인)

valued-de-rLI

영어 (미국)

values-en

values-en-rUS

영어 (영국)

values-en-rGB

영어 (캐나다)

values-en-rCA

영어 (호주)

values-en-rAU

영어 (뉴질랜드)

values-en-rNZ

영어 (싱가포르)

values-en-rSG

스페인어 (스페인)

values-es

values-es-rES

프랑스어 (프랑스)

values-fr

values-fr-rFR

프랑스어 (벨기에)

values-fr-rBE

프랑스어 (캐나다)

values-fr-rCA

프랑스어 (스위스)

values-fr-rCH

이태리어 (이탈리아)

values-it

values-fr-rIT

이태리어 (스위스)

values-fr-rCH

일본어 (일본)

values-ja

values-ja-rJP

한국어 (대한민국)

values-ko

values-ko-rKR

네덜란드어 (네덜란드)

values-nl

values-nl-rNL

네덜란드어 (벨기에)

values-nl-nBE

폴란드어 (폴란드)

values-pl

values-pl-rPL

러시아어 (러시아)

values-ru

values-ru-rRU

중국어 (중국)

values-zh

values-zh-rCN

중국어 (대만)

values-zh-rTW


출처 - http://arabiannight.tistory.com/107
2차출처 - http://blog.naver.com/heutwo/80159487563


-----------------

아무생각없이 에디트플러스로 작업하고 저장한다음에 빌드했더니 에러가 뙇! 하고 튀어나와서.. 고생했는데.. 천재형님의 도움을 얻어 해결함.
핵심은 파일 저장형식에 있었음.. 에디트 플러스는 기본 ANSI로 저장하는데 이를 UTF-8로 변경하고 저장한다음 빌드하면 정상적으로 적용됨.



WRITTEN BY
빨강꼬마

,

일단 에셋가격이 $30...

기존에 안드로이드단구현과 관련된 에셋은 prime31(안드로이드 인앱결제)밖에 없어서 이번 프로젝트엔 페북, 결제, 푸시등 다양한 네이티브 기능구현이 필요한 시점에 50%할인소식이 있을때 낼롬 구입하고 썩혀두었음..

막상 기능구현할 시점이 되서 이리저리살펴보는데 네이티브 기능구현단을 완전 쉽게 해두었다.

개인적으로는 페북 정책변경으로 일부 권한사용에 있어서 심사가 필요했던것과 로그인시 각 퍼미션을 직접 넣어야 했었다는 것을 빼면 별로 고생한게 없기도 하고..

조만간 프로젝트가 끝나는 대로 에셋 사용법에 대해 간단히 정리해두려고 한다. 'ㅅ'

'Unity > 스크립트' 카테고리의 다른 글

Swipe 판별  (0) 2015.07.20
Android 국가코드 정보  (0) 2015.06.07
String -> enum 변환  (0) 2015.02.17
기본 변수 저장시 암호화  (0) 2014.10.16
Playerprefs 암호화.  (0) 2014.10.14

WRITTEN BY
빨강꼬마

,

I've come across the situation on a number of occasions when coding where I've wanted to convert from a string to an enum. In the Media Catalog sample, I resorted to one giant switch statement that has a case block for each string that returns an enum from it.

One of my colleagues came up with the answer yesterday; it's one of those methods that you can never find when you're looking for it, but once discovered it seems blindingly obvious:

   object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

So you can write the following kind of code:

   enum Colour
   {
      Red,
      Green,
      Blue
   } 

   // ...
   Colour c = (Colour) Enum.Parse(typeof(Colour), "Red", true);
   Console.WriteLine("Colour Value: {0}", c.ToString());

   // Picking an invalid colour throws an ArgumentException. To
   // avoid this, call Enum.IsDefined() first, as follows:
   string nonColour = "Polkadot";

   if (Enum.IsDefined(typeof(Colour), nonColour))
      c = (Colour) Enum.Parse(typeof(Colour), nonColour, true);
   else
      MessageBox.Show("Uh oh!");

What a time saver - thanks, Simon!

Footnote: interestingly, whilst writing this up I noticed that Enum.IsDefined() doesn’t offer the ignoreCase parameter. If you don’t know whether the casing is right, it seems the only way to do the conversion is using the Parse method and catching the ArgumentException. That's not ideal, since it runs a lot slower. I wonder if this is a loophole in the design; no doubt someone like Brad could cast light on it...

posted on Friday, April 02, 2004 1:49 PM

Feedback

# re: How do you convert a string into an enum? 4/2/2004 7:22 PM SBC

You can get the string values of enums also by calling Enum.GetNames or Enum.GetName...




WRITTEN BY
빨강꼬마

,

결제 테스트때문에 외부 에셋 임포트하고 빌드하려니 갑자기 튀어나오는 에러! -ㅅ-;;;
구글검색 해보니 java 패스 어쩌고 저쩌고..


음.. 난 이미 패스고 뭐고 모든 설정을 했는데!!


그렇다면 왠지 jdk 버젼문제인가 하고 설치된 버젼을 살펴보니 jdk6버젼을 쓰고있었음..


임포트한 에셋에서 좀더 윗단계의 jdk를 사용해 jar파일을 만들었다면 나올법도 한것같아 잽싸게 jdk를 업뎃한 결과 에러가 사라짐~

'Unity' 카테고리의 다른 글

Unity 작업시 개인 Tip  (2) 2016.04.14
Android 다국어 셋팅시  (0) 2015.03.04
facebook 연동시 keytool not found 뜰때.  (0) 2014.12.23
유니티 <-> MS-SQL 연동.  (0) 2014.02.12
NGUI 기기별 해상도 셋팅시 코드  (0) 2013.11.21

WRITTEN BY
빨강꼬마

,

facebook sdk for unity 6.0 got very minor bug
They detect if u have keytool using following function in FacebookAndroidUtil.cs

private static bool DoesCommandExist(string command)
{
var proc = new Process();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
proc.StartInfo.FileName = "cmd";
proc.StartInfo.Arguments = @"/C" + command;
}
else
{
proc.StartInfo.FileName = "bash";
proc.StartInfo.Arguments = @"-c " + command;
}
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.CreateNoWindow = false; 
proc.Start();

proc.WaitForExit();

if (Application.platform == RuntimePlatform.WindowsEditor)
{
return (proc.ExitCode == 0);
}
else
{
return proc.ExitCode != 127;
}
}

If you open a command prompt and type keytool, it show up all the parameter that you can use for the command keytool.
It will not exit with exitCode 0 but 1 which means partially success as no parameter is provided for keytool. so the check for if you have keytool always failed.

Actually you can turn on shell by change proc.StartInfo.UseShellExecute = false; to true and you can see the parameter hint come out for the command keytool , which means keytool is there. it just the DoesCommanExist have a bug.

The fix is change
return (proc.ExitCode == 0);
to
return (proc.ExitCode == 0||proc.ExitCode == 1);

I know nothing about cmd but this page tell me, exitcode 1 mean partially succeed.
http://msdn.microsoft.com/en-us/library/ms194959(v=vs.100).aspx


출처 - http://forum.unity3d.com/threads/keytool-not-found-facebook-sdk-on-android-native-plugin.239696/




WRITTEN BY
빨강꼬마

,
가장 처음 만들었던 게임을 만들고 난 후에 가장 아쉬운 부분은 보안적인 처리가 취약했다는거.
(취약이라기 보다는 전무...)

이번 프로젝트를 진행하면서 내 자신이 그래도 어느정도는 만족할 만한 보안처리(클라이언트 기준)를 하고싶었고,
그래서 나온 결과물이

- PlayerPrefs 암호화 (사용자의 임의적인 값 변경을 해도 영향을 받지 않도록)
- 변수 암호화 (메모리 주소 스캔이 어렵도록)
- 클라이언트와 서버간 통신중 주고받는 데이터의 암호화

이중 2개는 처리했고 남은 이슈는 3번째 이슈인데 이것도 내일 아마 처리될듯 하다.

첫번째 암호화에 대해서는 이전 포스팅으로 기록을 남겼고,
이번 포스팅에서는 기본 변수를 어떻게 저장해야 메모리 스캔을 어렵도록 할수 있을까에 대한 포스팅이다.


아는 게 너무 없어서 이것저것 서칭해본 결과 아래의 클래스를 프로젝트에 만들어 두었다.

using System;

using System.Collections;

using System.Security.Cryptography;

using System.Text;


public static class SecureConverter

{

    private static int xorCode = (UnityEngine.Random.Range(0, 10000) + UnityEngine.Random.Range(0, 10000) + UnityEngine.Random.Range(0, 10000)).GetHashCode();

        

    public static int SecureInt(int data)

    {

        return  data ^ xorCode;

    }


    public static string SecureString(string data)

    {

        string newText = "";


        for (int i = 0; i < data.Length; i++)

        {

            int charValue = Convert.ToInt32(data[i]); //get the ASCII value of the character

            charValue ^= xorCode; //xor the value


            newText += char.ConvertFromUtf32(charValue); //convert back to string

        }


        return newText;

    }

}


사용은 아래처럼 저장할 변수와 프로퍼티를 관리하는 스크립트에 만들어 두고 프로퍼티로 접근하면 자동으로 암호화된 값이 저장되고, 불러올때는 복호화해서 불러오기 때문에 원래의 데이터 그대로를 사용할 수 있게 해두었다.

private int _abc;
public int abc { get { return SecureConvert.SecureInt(_abc); } set { _abc = SecureConvert.SecureInt(value); } }

어디서든 abc = 300; 과 같은 형태로 저장하면 실제 암호화된 형태로 저장되기 때문에 원시적인 데이터 검색만으로는 실제 메모리 주소를 찾기가 어렵게 된다.


추신. MD5 나 SHA1 같은 것으로 대체하면 더욱 좋을듯. 이는 추후 포스팅~


WRITTEN BY
빨강꼬마

,

아무런 처리 없이 PlayerPrefs를 사용할 경우 값이 그대로 노출되면서 접근이 가능하고, 프로그램 밖에서 값을 수정할 경우 수정된 값 그대로 프로그램에 적용되는 문제점이 있음.


그런고로 1차적으로 어느정도는 암호화해야 하는데..구글링 한 결과 아주 만족스럽지는 않지만 적어도 원하지 않는 값으로 프로그램에 적용되는 것을 막아주도록 작성된 내용을 유니티포럼에서 찾아 포스팅한다..

(출처 - http://forum.unity3d.com/threads/playerprefs-encryption.26437/)


아래 코드의 포인트는 테스트해본 결과 실제 저장되는 PlayerPrefs의 값은 원본 그대로 저장된다. 노출자체는 된다는 얘기지. 다만, 직접 해당 유저가 해당 값을 수정하면 CheckEncryption함수를 통과하지 못해 DEFAULT 값으로 처리되면서, 기존에 저장되어 있던 PlayerPrefs의 해당 키(3개)는 모두 삭제처리된다.


using UnityEngine;

using System.Collections;

using System.Security.Cryptography;

using System.Text;

 

public class EncryptedPlayerPrefs  {

 

    // Encrypted PlayerPrefs

    // Written by Sven Magnus

    // MD5 code by Matthew Wegner (from [url]http://www.unifycommunity.com/wiki/index.php?title=MD5[/url])

    

    

    // Modify this key in this file :

    private static string privateKey="9ETrEsWaFRach3gexaDr";

    

    // Add some values to this array before using EncryptedPlayerPrefs

    public static string[] keys;

    

    

    public static string Md5(string strToEncrypt) {

        UTF8Encoding ue = new UTF8Encoding();

        byte[] bytes = ue.GetBytes(strToEncrypt);

 

        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

        byte[] hashBytes = md5.ComputeHash(bytes);

 

        string hashString = "";

 

        for (int i = 0; i < hashBytes.Length; i++) {

            hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');

        }

 

        return hashString.PadLeft(32, '0');

    }

    

    public static void SaveEncryption(string key, string type, string value) {

        int keyIndex = (int)Mathf.Floor(Random.value * keys.Length);

        string secretKey = keys[keyIndex];

        string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);

        PlayerPrefs.SetString(key + "_encryption_check", check);

        PlayerPrefs.SetInt(key + "_used_key", keyIndex);

    }

    

    public static bool CheckEncryption(string key, string type, string value) {

        int keyIndex = PlayerPrefs.GetInt(key + "_used_key");

        string secretKey = keys[keyIndex];

        string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);

        if(!PlayerPrefs.HasKey(key + "_encryption_check")) return false;

        string storedCheck = PlayerPrefs.GetString(key + "_encryption_check");

        return storedCheck == check;

    }

    

    public static void SetInt(string key, int value) {

        PlayerPrefs.SetInt(key, value);

        SaveEncryption(key, "int", value.ToString());

    }

    

    public static void SetFloat(string key, float value) {

        PlayerPrefs.SetFloat(key, value);

        SaveEncryption(key, "float", Mathf.Floor(value*1000).ToString());

    }

    

    public static void SetString(string key, string value) {

        PlayerPrefs.SetString(key, value);

        SaveEncryption(key, "string", value);

    }

    

    public static int GetInt(string key) {

        return GetInt(key, 0);

    }

    

    public static float GetFloat(string key) {

        return GetFloat(key, 0f);

    }

    

    public static string GetString(string key) {

        return GetString(key, "");

    }

    

    public static int GetInt(string key,int defaultValue) {

        int value = PlayerPrefs.GetInt(key);

        if(!CheckEncryption(key, "int", value.ToString())) return defaultValue;

        return value;

    }

    

    public static float GetFloat(string key, float defaultValue) {

        float value = PlayerPrefs.GetFloat(key);

        if(!CheckEncryption(key, "float", Mathf.Floor(value*1000).ToString())) return defaultValue;

        return value;

    }

    

    public static string GetString(string key, string defaultValue) {

        string value = PlayerPrefs.GetString(key);

        if(!CheckEncryption(key, "string", value)) return defaultValue;

        return value;

    }

    

    public static bool HasKey(string key) {

        return PlayerPrefs.HasKey(key);

    }

    

    public static void DeleteKey(string key) {

        PlayerPrefs.DeleteKey(key);

        PlayerPrefs.DeleteKey(key + "_encryption_check");

        PlayerPrefs.DeleteKey(key + "_used_key");

    }

    

}


사용법은 PlayerPrefs의 사용법과 동일하다. (아래의 암호화를 위한 키를 추가한 후 사용하면 된다.) 

  EncryptedPlayerPrefs.keys=new string[5];


        EncryptedPlayerPrefs.keys[0]="23Wrudre";

        EncryptedPlayerPrefs.keys[1]="SP9DupHa";

        EncryptedPlayerPrefs.keys[2]="frA5rAS3";

        EncryptedPlayerPrefs.keys[3]="tHat2epr";

        EncryptedPlayerPrefs.keys[4]="jaw3eDAs";

사용시 PlayerPrefs 클래스 대신 EncryptedPlayerPrefs을 사용하면 된다. 키값 전부 지워주는 것은 기존대로 PlayerPrefs꺼 가져다가 쓰면 됨. 추후 빌드시 난독화 과정을 거치면 어느정도 보안처리를 했다고 볼수 있겠지. 


---- 10월 27일 추가.


위의 클래스를 사용하면 값이 그대로 보이기때문에, 이러한 문제를 해결하기위해서는 PlayerPrefs를 약간 가공해서 쓰는것도 한가지 방법이다.

특정 시크릿키를 사용해 Int일 경우 String으로 변환해서 변환된 문자열을 암호화하여 PlayerPrefs.SetString으로 저장하고 불러올때는 복호화 후 Convert 등을 이용해 다시 int 로 바꾸어 호출해 사용하는 방법이 좋아보인다.


이와 관련하여 암/복호화를 특정키를 사용하여 쉽게 할 수 있도록 하는 클래스는 검색하면 어느정도 나오니 그것을 이용해 구현하는 것이 적합.


---- 2015.06.17

http://ikpil.com/1342


WRITTEN BY
빨강꼬마

,