2017년 10월 31일 화요일

무라카미 하루키 스크랩


뭔가를 비난한다는 것, 엄격하게 비평하는 것 자체를 잘못이라고 말하는 것이 아니다. 모든 텍스트는 온갖 비평에 열려 있는 것이고, 또 열려 있어야 한다. 다만 내가 여기서 말하고 싶은 것은, 뭔가에 대한 네거티브한 방향의 계몽은 경우에 따라서는 여러 가지 사물을, 때로는 자기 자신까지도, 돌이킬 수 없을 정도로 훼손시켜버리고 만다는 사실이다. 그런 부정에는 보다 크고 따뜻한 포지티브한 '보상'같은 것이 마련되어 있어야 할 것이다. 그러한 뒷받침이 없는 네거티브한 연속적인 언동은, 즉효성이 있는 주사에 중독되는 것과 마찬가지여서, 일단 앞으로 나가기 시작하면 되돌릴 수 없다는 사실을 명심해두지 않으면 안 된다.


물론 내게도 작가나 작품에 대한 기호라는 것이 있다. 사람에 대한 기호도 있다. 하지만 그 옛날에 들었던 테네시 윌리엄스의 강의를 상기할 적마다 '역시 남에 대한 험담은 쓰지 말자.' 하고 절실히 생각한다. 그보다는 차라리 "이건 좋습니다, 아주 재미있습니다." 라고 말하고, 그와 똑같이 생각하고, 재미있다고 기뻐해주는 사람을 비록 소수라도 괜찮으니 발견하고 싶다. 이것은 와세다 대학 문학부가 내게 준 몇 안되는 산 교훈 중 하나이다.


그러나 오늘날의 이 즉흥적 사회에서 그런 유유한 태도를 유지하면서 살다 보면, 때때로 나 자신이 바보처럼 느껴질 때도 있다. 그보다는 목청을 높여서 통렬하게 누군가를 매도하는 쪽이 훨씬 더 스마트하게 보인다. 예를 들어, 작가보다는 비평가 쪽이 똑똑한 것처럼 보인다. 그렇지만 설령 개별 작가가 때로는 어리석게 보인다 하더라도(또 실제로 어리석다 하더라도), 무에서 뭔가를 만들어내는 작업이 얼마나 손이 가는 괴로운 작업인지를 몸소 경험하여 알고 있기 때문에, 그것을 한마디로 "저 녀석은 쓰레기다, 이건 허섭스레기다." 라고 매도해서 끝내버리는 일은 할 수 없다. 작품이 좋은 싫든간에. 이것은 작가로서의 내 생활 태도의 문제이며, 어떤 의미에서는 존엄의 문제이다.


 - 무라카미 하루키, 비밀의 숲 85, 86 페이지에서

2017년 10월 14일 토요일

타임서버에서 시각 가져와서 Unity 에서 사용하기 (NST, NIST)

NIST 타임서버에서 시간가져오기 (NST)

아래와 같은 코드로 가져올 수 있다.
Unity 에서 사용할 수 있다.


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

public class TimeServer : MonoBehaviour {

    [SerializeField]
    private string _comment = "만료시킬 날짜를 적으세요 (한국시각 기준)";

    public int _yyyy, _mm, _dd;
    private DateTime _expireDateTime, _nowServerDateTime, _nowLocalDateTime;
    private TimeSpan _duration;

 // Use this for initialization
 void Start () {

        // 한국 시각
        _duration = System.TimeSpan.FromHours(9);
        _expireDateTime = new DateTime(Mathf.Clamp(_yyyy, 1900, 3000), Mathf.Clamp(_mm, 1,12), Mathf.Clamp(_dd, 1, 31));

        _nowLocalDateTime = DateTime.Now;
        _nowServerDateTime = GetNISTDate().Add(_duration);

        if (Debug.isDebugBuild)
        {
            Debug.LogWarning("만료지정일 : " + _expireDateTime);
            Debug.LogWarning("현재 로컬 시각 :" + _nowLocalDateTime);
            Debug.LogWarning("현재 서버 시각 :" + _nowServerDateTime);
        }

        if (_nowLocalDateTime < _expireDateTime)
        {
            if (_nowServerDateTime < _expireDateTime)
            {
                // Debug.Log("실행");
            }
            else
            {
                // Debug.Log("서버 체크 결과 만료 됨");
            }
        }
        else
        {
            // Debug.Log("로컬 체크 결과 만료 됨");
        }


    }

#region NTPTIME

    //NTP time 을 NIST 에서 가져오기
    // 4초 이내에 한번 이상 요청 하면, ip가 차단됩니다.

    public static DateTime GetDummyDate()
    {
        return new DateTime(2017, 12, 24); //to check if we have an online date or not.
    }

    public static DateTime GetNISTDate()
    {
        System.Random ran = new System.Random(DateTime.Now.Millisecond);
        DateTime date = GetDummyDate();
        string serverResponse = string.Empty;

        // NIST 서버 목록
        string[] servers = new string[] {
        "time.bora.net",
        //"time.nuri.net",
        //"ntp.kornet.net",
        //"time.kriss.re.kr",
        //"time.nist.gov",
        //"maths.kaist.ac.kr",
        "nist1-ny.ustiming.org",
        "time-a.nist.gov",
        "nist1-chi.ustiming.org",
        "time.nist.gov",
        "ntp-nist.ldsbc.edu",
        "nist1-la.ustiming.org"
    };

        // 너무 많은 요청으로 인한 차단을 피하기 위해 한 서버씩 순환한다. 5번만 시도한다.
        for (int i = 0; i < 5; i++)
        {
            try
            {
                // StreamReader(무작위 서버)
                StreamReader reader = new StreamReader(new System.Net.Sockets.TcpClient(servers[ran.Next(0, servers.Length)], 13).GetStream());
                serverResponse = reader.ReadToEnd();
                reader.Close();

                // 서버 리스폰스를 표시한다. (디버그 확인용)
                if (Debug.isDebugBuild)
                    Debug.Log(serverResponse);

                // 시그니처가 있는지 확인한다.
                if (serverResponse.Length > 47 && serverResponse.Substring(38, 9).Equals("UTC(NIST)"))
                {
                    // 날짜 파싱
                    int jd = int.Parse(serverResponse.Substring(1, 5));
                    int yr = int.Parse(serverResponse.Substring(7, 2));
                    int mo = int.Parse(serverResponse.Substring(10, 2));
                    int dy = int.Parse(serverResponse.Substring(13, 2));
                    int hr = int.Parse(serverResponse.Substring(16, 2));
                    int mm = int.Parse(serverResponse.Substring(19, 2));
                    int sc = int.Parse(serverResponse.Substring(22, 2));

                    if (jd > 51544)
                        yr += 2000;
                    else
                        yr += 1999;

                    date = new DateTime(yr, mo, dy, hr, mm, sc);

                    // Exit the loop
                    break;
                }
            }
            catch (Exception e)
            {
                /* 아무것도 하지 않고 다음 서버를 시도한다. */
            }
        }
        return date;
    }
    #endregion
}


아래 코드 원본에서 주석 변경 및 내가 사용하기 위해 수정함.
경로 : https://stackoverflow.com/questions/516788/getting-current-gmt-time

2017년 9월 18일 월요일

Unity Custom Menu 만들기

귀찮은 작업이라고 생각해서 잘 안하는 편이었는데...
오늘 처럼 뭔가 단순하게 반복해야 하는 작업에는 메뉴로 등록하고 빨리 적용하는게 나을 것 같았다.

작업 내용은 어떠한가 하니
1. 어떤 오브젝트에 필요한 새 컴포넌트를 붙이고,
2. 구 컴포넌트의 값을 새 컴포넌트로 옮기고,
3. 구 컴포넌트를 삭제한 뒤,
4. 주석용으로 사용하는 컴포넌트를 붙여서 작성시각을 기록한다.

일괄로 하기엔 확인하면서 진행해야 해서 메뉴를 이용하는 정도가 딱 좋았다.
(컨텍스트 메뉴가 나았을지도? (웃음))

참고한 Document
https://docs.unity3d.com/ScriptReference/EditorGUILayout.html

예제는 이거면 금방 알 수 있다. (Toggle 레퍼런스에서 옮김)
필요한 변수를 선언하고
editorLayout 으로 연결하고
거기서 조작에 따라 처리할 내용을 기입하면 된다.


using UnityEngine;
using UnityEditor;

public class EditorGUILayoutToggle : UnityEditor.EditorWindow
{
    bool showBtn = true;

    [MenuItem("Examples/Editor GUILayout Toggle Usage")]
    static void Init()
    {
        EditorGUILayoutToggle window = (EditorGUILayoutToggle)EditorWindow.GetWindow(typeof(EditorGUILayoutToggle), true, "My Empty Window");
        window.Show();
    }

    void OnGUI()
    {
        showBtn = EditorGUILayout.Toggle("Show Button", showBtn);
        if (showBtn)
            if (GUILayout.Button("Close"))
                this.Close();
    }
}

2017년 9월 14일 목요일

Android Shell 로 뒤로가기(Back) 버튼 입력하기


Run Shell 에서 아래 커맨드를 입력한다. Root 권한이 있을 때만 실행이 가능하다.
Tasker 등에서 뒤로가기를 실행 해야 하는데 메뉴가 없을 때 유용하다.



input keyevent 4

//혹은

input keyevent 187

2017년 9월 8일 금요일

Unity Editor 를 켤 때 마다 무언가를 실행하기 (버전 정보 갱신)

버전 정보를 빌드 할 때 마다 일일히 써주는게 귀찮았다.

빌드 전에 버전 정보를 갱신해주는 스크립트를 돌리면 되는데,
아래 두가지 이유로 에디터를 켤 때 (포커스가 올 때?) 마다 버전 정보를 갱신해 줬다.
1. 다른 사람이 세팅한 빌드 머신을 건드리기 귀찮아서
2. 에디터 건드릴 때 마다가 좋아서

여튼 아래는 간단히 짠 코드
버전 정보의 형식은 예시로 적당히 쓴 것이다.
4단위로 1.0.년.월일
예) 1.0.17.1159

혹시 실행이 안되거나 권한 없음 오류가 나면, 유니티 에디터를 실행할 때 관리자 권한으로 실행하면 된다.


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

[InitializeOnLoad]
public class Startup
{
    static Startup()
    {
        string VersionInfo = "1.0." + string.Format("{0:00}", System.DateTime.Now.Year).Substring(2, 2) + "." + string.Format("{0:00}", System.DateTime.Now.Month) + string.Format("{0:00}", System.DateTime.Now.Day);
        System.IO.File.WriteAllText(Application.dataPath + "/Resources/AppVersionInfo.txt", VersionInfo.ToString());
        Debug.LogWarning("오늘의 버전 정보 갱신 : " + VersionInfo + "\n저장 경로 : " +Application.dataPath+"/Resources/AppVersionInfo.txt");
    }
}

2017년 9월 7일 목요일

게임 컨트롤러의 스위치를 와이어로 연결할 때 와이어 구매 팁 (컨트롤러 자작)

브레드보드용 와이어를 쉽게 구해서 사용할 수 있는데,
얇은 선이 꼬인 것을 연선, 굵은 선 한가닥을 단선이라고 한다.
게임 스위치용으로는 단선이 좋다.

연선으로 해도 동작은 하는데, 미묘하게 레이턴시가 생긴다.

2017년 9월 5일 화요일