2013년 7월 28일 일요일

이미지 폰트

#pragma strict

var tex : Texture2D[] =new Texture2D[10];
var score:int;

function Awake(){
score = 25634;
}

function Update () {
score+=1*Time.time;

}


function OnGUI(){
//simplemode = 세가지 제공.. 그중 아래는 사간 화면 꽉 제운것...  true = 알파 브랜딩 오케이

noOkDraw(score,Screen.width/30*0.75,Screen.width/30,10);



}

function noOkDraw(nocheck:int,noSizeXpos:float,noSize:float,noSizeYpos:float){


var a0 =  nocheck/10000; // 첫번째 숫자
var a1 =  nocheck%10000; // 나머지로 다음 숫자들을 찾은 다음
var a2 =  a1/1000; // 두번째 숫자
var a3 =  a1%1000; // 나머지로 다음 숫자들을 찾은 다음
var a4 =  a3/100; // 세번째 숫자
var a5 =  a3%100; // 나머지로 다음 숫자들을 찾은 다음
var a6 =  a5/10; // 네 번째 숫자
var a7 =  a5%10; // 나머지로 다음 숫자들을 찾은 다음
var a8 =  a7/1; // 다섯번째 숫자
var a9 =  a7%1; // 나머지로 다음 숫자들을 찾은 다음

GUI.DrawTexture(new Rect(noSizeXpos*2,noSize*noSizeYpos,   noSize,  noSize),tex[a0], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*3,noSize*noSizeYpos,   noSize,  noSize),tex[a2], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*4,noSize*noSizeYpos,   noSize,  noSize),tex[a4], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*5,noSize*noSizeYpos,   noSize,  noSize),tex[a6], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*6,noSize*noSizeYpos,   noSize,  noSize),tex[a8], ScaleMode.StretchToFill, true, 0.0F);

}

2013년 7월 25일 목요일

데이터 저장

  • 게임 데이터를 게임이 종료된 후에도 사용할 수 있도록 저장하고 싶은 경우
  • 기본 타입(type)의 데이터 말고 좀 더 복잡한 데이터를 저장하고 싶은 경우
위의 경우에 해당되신다면 이번 튜토리얼이 유용할 수 있습니다.

개요
유니티에서 데이터를 저장하는 게 생각만큼 쉽지 않는 건 사실입니다. 전체 씬, 플레이어 위치 정보 등을 저장하려는 경우에그 작업량이 만만치 않습니다. 이번 튜토리얼 그리고 후에 있을 튜토리얼을 통해 유니티에서 데이터를 저장하는 좀 더 쉬운 방법을 보여드리겠습니다. 이번 튜토리얼에서는 데이터를 저장하는 몇 가지 다른 방법들과 이렇게 저장된 데이터들을 RPC 연결 / 서버에 전달해서, 게임에 사용하는 방법을 보여드리겠습니다.

가장 기본적인 방법
기본적인 방법부터 시작해 보겠습니다. 단순한 데이터형(type)에 대해서는 여러분께서 잘 알고 계실 PlayerPrefs으로 저장하는 방법을 확인 하는 차원에서 한번 알아보도록 하겠습니다. PlayerPrefs는 기본형의 데이터를 문자열키 (string key) 값과 함께 저장할 수 있도록 해줍니다. 단순한 데이터를 저장하고 불러와 사용하기에 좋은 방법입니다. 
게임 내의 값들
씬 전환 시에 데이터를 저장하고 이를 공유하고 싶은 경우에 좋은 방법 중 하나는 정적 클래스 (static class)를 만들어 이 클래스에 데이터를 저장하는 방법입니다.
그리고 이 값을 읽고 싶을 때는 아래와 같이 사용하면 됩니다.
이와 같은 클래스를 사용하는 방법의 단점은 인스펙터(Inspector)에서 값을 조절할 수 없다는 점 입니다. (싱글톤으로 매니져 클래스를 구성하면 이 점은 보완할 수 있습니다..)
- 인스펙터와 코드 모두에서 값을 조절하고 싶은 경우에는 DontDestroyOnLoadobject 함수를 이용하는 방법을 고려할 수 있습니다. (아래 코드 참고)


그리고 아래와 같은 방법으로 값에 접근할 수 있습니다.


좀 더 복잡한 데이터 저장하기
위의 예제에서 PlayerPrefs를 사용해서 high score를 저장하는 방법을 살펴봤습니다. 하지만 위에서 살펴본 방법으로는 많은 데이터를 저장하는 데에는 한계가 있습니다. 따라서 아래와 같이 high score를 저장할 수 있는 테이블을 정의해서 저장하는 방법을 고려해볼 때가 왔습니다.
위의 예제를 살펴보면, List를 이용해서 ScoreEntry 클래스 정보를 담아 테이블처럼 사용합니다. 하지만 이 정보를 어떻게 저장해야 할까요? – 바로 BinaryFormatter를 사용하면 됩니다! BinaryFormatter를 사용해서 “파라미터를 갖지 않는 생성자”를 갖는 클래스라면 어떤 클래스도 바이트 배열로 변환하고, 변환된 배열을 다시 문자열 값으로 변환할 수 있습니다. (문자열 값으로 변환하면, PlayerPrefs에 저장할 수 있겠죠?) 아래 보이는 네임 스페이스들을 추가해줘야 한다는 점을 잊지 마시구요.
유니티 오브젝트 저장하기
유니티 오브젝트들을 저장하는 방법은 생각보다 까다로울 수 있습니다. 그래서 대부분 유니티 오브젝트가 갖는 값을 유추해 볼 수 있는 클래스를 새로 생성하고 이 클래스의 값을 저장합니다. 예를 들면, RPC 호출을 통해 여러 개의 AnimationStates를 전달하고 싶은 경우에, AnimationStates를 대신할 수 있는 클래스를 생성해서 이 값을 전달하게 됩니다. 다른 유니티 오브젝트의 값을 전달하려는 경우에도 상황은 마찬가지겠지요.
RPC를 통해 전달하기
아래 코드를 보면, 어떤 클래스라도 문자열로 변환할 수 있도록 하는 방법을 보여줍니다. 이를 이용하면 RPC를 통해 모든 파라미터 값을 보낼 수 있겠죠?
문서화 되지는 않았지만, RPC 역시 byte[]을 보낼 수 있습니다. 이 값은 BinaryFormatter를 이용해서 우리가 원하는 값으로 바로 변환할 수 있도록 도와줍니다. 문자열로부터 변환하는 시간을 줄여주기 때문에 더 좋다고 할 수 있습니다.

이제 highscores 값을 다른 플레이어에 전달할 수 있도록 하는 능력이 갑자기 생겼네요.


웹으로 전달하기
WWWForm 을 이용해서 웹 서버에 데이터를 전달하는 방법은 아주 쉽습니다. 하지만 위에서 보았듯이 Convert.ToBase64String()를 이용해서 바이너리 데이터를 문자열로 변환하는 방법이 제일 쉽지 않을까 생각되네요. (물론 여러분이 사용하시는 서버에 따라 달라질 수 있습니다)
파일로 저장하기
파일로 저장하는 방법도 물론 쉽습니다. 유니티가 제공하는 Application.persistentDataPath를 이용해서 파일을 저장할 위치를 정하고, MemoryStream 대신 FileStream 을 사용하면 됩니다.


결론
이번 튜토리얼을 통해서, 데이터를 저장하고 게임 중에 이 값들을 이용하는 몇몇 새로운 방법들을 익히셨으리라 생각합니다.

출처 http://unitygems.com/saving-data-1-remember-me/
위의 자료 번역했습니다. 처음 번역한거라..많이 부족하지만 읽어 주셔서 감사하고, 원문 확인 하셔도 좋을 것 같습니다.

2013년 7월 13일 토요일

GameControll

#pragma strict


public enum GameState { playing,bonus, gameover };  // 게임 상태 현재는 세가지..

    public var  platformPrefab : Transform;  // 프레팹을 담을 변수
    public static var gameState:GameState; // 게임 상태 저장 변수

    private var playerTrans:Transform ; // 참조할 플레이어를 담을 변수
    private var platformsSpawnedUpTo :float  = 0;  // 얼만큼 위에서 나타날 것인가
    private var platforms: ArrayList ;  // 담을 배열
    private var nextPlatformCheck:float  = 0.0f;  // 다음번엔 어느 정도 위치에 나타나나?

function Awake () {
    playerTrans = GameObject.FindGameObjectWithTag("Player").transform;  // 플레이어를 참조하고
    platforms = new ArrayList(); // 새로운 배열을 만든다.

    SpawnPlatforms(25.0); 플랫폼 발생 함수... 위에 25정도 위에 나타나게 한다.
    StartGame();  // 게임을 진행하는 함수.. 게임스테이트를 변하게 한다.
}


function Start ()
{
    Time.timeScale = 1.0f;  // 플레이..
    gameState = GameState.playing;  // 게임중으로 바꿈..
}


function StartGame()
    {
        Time.timeScale = 1.0f;
        gameState = GameState.playing;
    }

function GameOver()
    {
        Time.timeScale = 0.0f; //멈춤
        gameState = GameState.gameover; // 상태변수
        GameGUI.SP.CheckHighscore();
    }


function Update () {
        //Do we need to spawn new platforms yet? (we do this every X meters we climb)
        var playerHeight:float  = playerTrans.position.y;
        if (playerHeight > nextPlatformCheck)
        {
            PlatformMaintenaince(); //Spawn new platforms
        }

        //Update camera position if the player has climbed and if the player is too low: Set gameover.
        var currentCameraHeight:float  = transform.position.y;
        var newHeight:float = Mathf.Lerp(currentCameraHeight, playerHeight, Time.deltaTime * 10);
        if (playerTrans.position.y > currentCameraHeight)
        {
            transform.position = new Vector3(transform.position.x, newHeight, transform.position.z);
        }else{
            //Player is lower..maybe below the cameras view?
            if (playerHeight < (currentCameraHeight - 10))
            {
                GameOver();
            }
        }

        //Have we reached a new score yet?
        if (playerHeight > GameGUI.score)
        {
            GameGUI.score = playerHeight;
        }
}

    function PlatformMaintenaince()
    {
        nextPlatformCheck = playerTrans.position.y + 10;

        //Delete all platforms below us (save performance)
        for(var i:int = platforms.Count-1;i>=0;i--)
        {
            var plat:Transform = platforms[i];
            if (plat.position.y < (transform.position.y - 10))
            {
                Destroy(plat.gameObject);
                platforms.RemoveAt(i);
            }          
        }

        //Spawn new platforms, 25 units in advance
        SpawnPlatforms(nextPlatformCheck + 25);
    }


    function SpawnPlatforms(upTo:float )  // 일종의 간격
    {
        var spawnHeight:float  = platformsSpawnedUpTo;  // 세로간격
        while (spawnHeight <= upTo) // 보다 작으면 반복
        {
            var x:float  = Random.Range(-10.0f, 10.0f); // x 위치 좌우 위치...나중에 레이로 쏴서 체크
            var  pos :Vector3 = new Vector3(x, spawnHeight, 12.0f); // x 좌표를 기반으로 간격

            var plat:Transform  = Instantiate(platformPrefab, pos, Quaternion.identity); // 프레펩을 pos 위치에 붙인다. 회전 없이
            platforms.Add(plat); // 배열에 집어 넣는다.

            spawnHeight += Random.Range(1.6f, 3.5f); // 세로 간격
        }
        platformsSpawnedUpTo = upTo;
    }

javascript class 사용법

class itemClass {

var walkSpeed:float = 3.0;
var runSpeed:float  = 10.0;
var inAirControlAcceleration:float  = 1.0;
        var gravity:float  = 60.0;
var maxFallSpeed:float = 20.0;

}

var itemacess : itemClass;


itemacess.walkSpeed=15.0;

많은 변수들을 관리하기 어려울 때...
클래스를 만들어서 관리하면 편합니다.