2013년 12월 25일 수요일

[puzzle] 배치.

배치가 먼저...
배치 하면서..  배열을 통해.. 해당 이름과 게임 오브젝트를 저장..
이름은.. 넘버링을 해서.. 나중에 참조하기 위해.. 1_1 뭐 이런식으로 저장..
게임오브젝트를 저장하는 것은.. 이를 기본 배열로 사용하기 위해..

이것과 다르게.. 미리 배열을 만들어.. 참조하는 방법도 있습니다.
그게 옳은것 같은데.. 뭐.. 하다 보니.. 이렇게 됐네요.



using UnityEngine;
using System.Collections;

public class csManager : MonoBehaviour {

// 보글 변수..
public static GameObject blue;
public static GameObject red;
public static GameObject green;
public static GameObject yellow;
public static GameObject pupple;
GameObject block_bank;
string block_namelist;



int rows = 7;
int cols = 6;
int totlakind = 5;
bool canDelete=false;

public static int [,] randonList; // 무늬를 저장..
private GameObject  [,] bogles; // 게임 오브젝트를 저장..


void Awake(){

randonList = new int[rows,cols];
bogles = new GameObject [rows,cols];

blue=Resources.Load("Prefabs/blue") as GameObject;
red=Resources.Load("Prefabs/red") as GameObject;
green=Resources.Load("Prefabs/green") as GameObject;
yellow=Resources.Load("Prefabs/yellow") as GameObject;
pupple=Resources.Load("Prefabs/pupple") as GameObject;

}


void Start () {
block_bank = GameObject.Find("Block_Bank");

// 기본 시작 위치..
float pos_x=-2.5f;
float pos_y=-1.0f;


//2중 포문으로.  배치 한다..
for(int i=0; i<rows;i++)
{

for(int j=0; j<cols;j++)
{
//int k = Random.Range(0,totlakind);
// 배열에서.. 보글의 칼라를 참조..
randonList[i,j] = Random.Range(0,totlakind);
// 프레펩을.. 정한다..
GameObject block = null;
if(randonList[i,j]==0)
{
block = blue; // 프리펩을.. 정하고..
block_namelist=i+"_"+j;  // 이름을 만든다.
}
if(randonList[i,j]==1)
{
block = red;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==2)
{
block = green;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==3)
{
block = yellow;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==4)
{
block = pupple;
block_namelist=i+"_"+j;
}
// 게임오브젝트 배치..
GameObject temp = Instantiate(block,new Vector3(pos_x, pos_y, 0),transform.rotation) as GameObject;
temp.transform.parent = block_bank.transform; // 블록 뱅크 밑에.. 위치..
temp.name = block_namelist;
bogles[i,j] =temp;



pos_x++; // x 만큼.. 우측으로..


}
pos_y++; // y만큼 위로..
pos_x = -2.5f; // 새로 시작하는 위치..


}
//배열 확인.. 구동 되는지..
Debug.Log(bogles[0,0].gameObject.tag);

}




}

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;

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


2013년 6월 26일 수요일

unity3D animation

유니티를 이용하여 에니메이션을 하려면 방법은 여러가지다...

1) 스프라이트 에니메이션

랜더링 이미지던.. 수작업 이미지던 간에.. 이를 한 판에 몰아넣고.. 에니메이션을 하는 방법인데... 이런 방법론은..

수정이 용이치 않기 때문에...한번 작업하면 끝까지 가는 경우가 많다.
그렇기 때문에 낱장으로 작업을 하여.. 해당 폴더에 있는 이미지를 통으로 순차적 에니를 하는 경우가 많은데...

문제는 핸드폰에서는 이런 방법론은 지양해야 한다는 것이다.
퍼포먼스 문제인데...

대신 다른 방법론으로...

NGUI 와 같은 툴깃을 사용하는 것이다...
이경우..

문제는 C#에 능통해야 한다...
간단하에 뭘 고치는 수준이라면 몰라도.. 이게 프로그램 전반적으로 영향을 주려면..
C#에 능통하지 않으면..오히려 맨바닥에 하는 것 보다 어렵다..

처음 게임을 개발하는 이들에게 절대 권하고 싶지 않은 방법이다.

하지만.. 의외로 유니티를 이용해서 2d 게임을 하고자 하는 사람들이 많아... 적극적으로 고려해봐야 하는 것이 사실이다...


a. ngui 와 같은 툴깃을 사용한다.
b. unity 에서 한통에 이미지를 모두 붙여 작업한다.
c. unity 에서 랜더링 이미지를 교체하여 낱장으로 작업한다.

2) 로프트 에니

각각의 플랜을 기반으로 에니메이션을 한다.
즉, 낱장의 플랜에 캐릭터를 부분 맵핑하여 작업 한다.

이경우에 방법론은 두가지인데.. 둘다..
일단 맥스에서 축을 가져와야 한다는 것은 똑같다

맥스에서 플랜에 맵핑하여 캐릭터를 만든 후
각 플랜에 맵핑으로 얼굴 다리 손등을 표현하고
이를 링크시켜서.. 각각의 플랜의 축을 만든다.

이후..
a. 맥스에서 작업하고 모든 에니를 담은 fbx 파일로 export 하여 유니티로 가져온다.
b. 맥스에서 축까지 만든 화일을 가져와서.. unity에서 에니 작업을 한다.

일단 a 방법은 무난하고 쉽다.
b 방법은 만만하지 않다.

그러나.. b는 anim 으로 작업되기 때문에 60프레임까지 나온다.
a 방법은 anim을 fbx에서 추출해야 한다....
결국 추천할 방법은 a 방법이다.

3) 3d 에니..

유니티가 가장 기본적으로 제공하는 방법이며..
방법론은 2번 과 같다.


2. export와 import

일단.. 맥스에서 export 하는 것은 쉽다...
그러나.. 여러가지 주의를 해야 하는데...

먼저...
모든 모델링은 기본 더미가 있어야 한다.
물론 유니티에서 빈 게임 오브젝트로 해도 된다.
두번째.. 달라진 축에 맞춰 작업해야 한다.

기본적으로 export 옵션도 있지만..
back을 보고 작업해야 유니티에 맞다....

유니티에서 돌릴수도 있지만.. 에니메이션 기본 방향을 참조한다...
괜히 삽질하지 말고..
그냥 무식하게 작업하자..

문제는 import 다...
유니티가 발전하여 지금은 ani 방법론이 좀 달라졌다..
이게 옳은 방법이나 어렵다...

기존에 하던대로 하자...

import 옵션을 조절하여
이전 방법으로 사용한다.

제대로 했으면...
fbx 로 만든 프리팹에.. 에니메이션 컴포넌트가 같이 들어온다....
플레이 했을때
에니메이션이 바로 된다면.. 성공..

animator이 들어왔다면...
컨트롤로를 사용해야 하며... import 옵션 조절 실패...
이걸 사용해서 하려면.. 좀더 공부하길...
프로젝트도 더 큰 것이어야 한다.















2013년 6월 21일 금요일

unity3d - max import

살짝 욕 나온다...
책이나.. 블로그에 나오는 글이나..
또 공식 레퍼런스에도...
기본만 나왔지.. 실제 작업은 힘들다.....

결국 실무에서 배워야 된다는 이야긴데...

일단. 이걸 주의하자..

먼저..

1) 맵핑은 한 개로 몰아서 가져온다.
여러개로 나눠서 가져와도 되나..
일단 관리하기 힘들고..
이단... 퍼포먼스 많이 먹는 단다...

2) fbx 임포트가 다가 아니다..
실제 신에 올리려면...
fbx 후에도.. mesh filter 로 메시를 찾고...
mesh renderer 로 맵핑을 해줘야 한다...
그냥 안들어 온다..

3) 뼉따귀로 가져온다...
뼉따귀로 가져와야.. 사용할 수 있다.


일단 이게 세개 지켰나?
그럼.. 다음 작업에 들어간다...







2013년 6월 19일 수요일

buttonScript //버튼 스크립트

public var Anim : GameObject;  // 에니메이션 할 오브젝트


piblic var DoClickScale = true;
public Vector3 ClickScale = new Vector3(0.1f, 0.05f, 0.025f); // 클릭했을 때 커치는 크기 - 위치로 조절 했다... 조금 앞으로 다가옮

public var ButtonHoverColor : Color  = Color.white; // 버튼 기본
public var TextHoverColor : Color  = Color.red; // 버튼 올렸을 때




    
function Update(){
// ray로 만든 3d 버튼
        if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended) // 화면을 눌렀을 경우
        {
            Ray ray = Camera.main.ScreenPointToRay(new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y)); // 동일 위치를 눌렀을 경우
            if (collider.bounds.IntersectRay(ray)) //레이에 닿았을 때 반응..
            {
       if (DoClickScale)  // trun면
        renderer.transform.localScale += ClickScale;
       renderer.material.color = ButtonHoverColor; // 칼라를 바꾼다.
       transform.Find("Text").gameObject.renderer.material.color = TextHoverColor; // 텍스트에 닿았을 때 레드를 바꾼다.

if (Anim != null) // 에니메이션 있다면
Anim.animation.Play("ani"); // 플레이..

                if (name == "Btn_Quit") // 하이어라키의 오브젝트 이름
                {
                    Application.Quit();
                }
                else if (name == "Btn_Play")
                {
                    Application.LoadLevel("LevelSelect");
                }
                else if (name == "Btn_Practice")
                {
                    Game.Instance.StartPractice();
                }
                else if (name == "Btn_Options")
                {
Application.LoadLevel("OptionsMenu");
                }
                else if (name == "Btn_Back")
                {
                    Game.Instance.OnGotoMainMenu();
                }
            }
        }

}


실제 gui로 만드는 것 보타... 이런식의 3d 버튼을 사용하는게 좋을 때가 많습니다.
쓸데 없이.. 화면 위치 조작 안해도 되고...
카메라를 기준으로 하는 것이니 대충 맞게 쓸수 있습니다

물론 정확하게 같은 규격으로 하려면.. 고생 좀 하겠습니다만...




2013년 6월 17일 월요일

PlayerMovement

#pragma strict

  public var  movementSpeed : float = 5.0f;
  private var  isGrounded : boolean = false;


function Start () {

}

function Update () {


        rigidbody.velocity = new Vector3(0, rigidbody.velocity.y, 0); //Set X and Z velocity to 0

        transform.Translate(Input.GetAxis("Horizontal") * Time.deltaTime * movementSpeed, 0, 0);

        /*if (Input.GetButtonDown("Jump") && isGrounded)
        {
            Jump(); //Manual jumping
        }*/


}

function Jump()
    {
        if (!isGrounded) { return; }
        isGrounded = false;
        rigidbody.velocity = new Vector3(0, 0, 0);
        rigidbody.AddForce(new Vector3(0, 700, 0), ForceMode.Force);      
    }

function FixedUpdate()
    {
        isGrounded = Physics.Raycast(transform.position, -Vector3.up, 1.0f);
        if (isGrounded)
        {
            Jump(); //Automatic jumping
        }
    }

GameControll

#pragma strict


public enum GameState { playing, 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);
    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; //Pause the game
        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);
            var  pos :Vector3 = new Vector3(x, spawnHeight, 12.0f);

            var plat:Transform  = Instantiate(platformPrefab, pos, Quaternion.identity);
            platforms.Add(plat);

            spawnHeight += Random.Range(1.6f, 3.5f);
        }
        platformsSpawnedUpTo = upTo;
    }

GameGUI

#pragma strict


public static var SP : GameGUI ;
public static var score: int ;
private var bestScore:int  = 0;

function Awake()
{
     SP = this;
     score = 0;
     bestScore = PlayerPrefs.GetInt("BestScorePlatforms", 0);
   
}
function OnGUI()
    {
        GUILayout.Space(3);
        GUILayout.Label(" Score: " + score);
        GUILayout.Label(" Highscore: " + bestScore);

        if (GameState.gameState == GameState.gameover)
        {
            GUILayout.BeginArea(new Rect(0, 0, Screen.width, Screen.height));

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.BeginVertical();
            GUILayout.FlexibleSpace();

            GUILayout.Label("Game over!");
            if (score > bestScore)
            {
                GUI.color = Color.red;
                GUILayout.Label("New highscore!");
                GUI.color = Color.white;
            }
            if (GUILayout.Button("Try again"))
            {
                Application.LoadLevel(Application.loadedLevel);
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndVertical();
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.EndArea();

        }
    }

    public function CheckHighscore()
    {
        if (score > bestScore)
        {
            PlayerPrefs.SetInt("BestScorePlatforms", score);
        }
    }

2013년 6월 16일 일요일

Vscroll.cs

using System.Collections;

public class Vscroll : MonoBehaviour {

public Joystick[] moveTouchPad;
public Joystick[] jumpTouchPad;


public float forwardSpeed = 4.0f;
public float backwardSpeed = 4.0f;
public float jumpSpeed = 16;
public float inAirMultiplier = 0.25f; // Limiter for ground speed while jumping

private Transform thisTransform;
private CharacterController character;
private Vector3 velocity; // Used for continuing momentum while in air
private bool canJump = true;

// Use this for initialization
void Start () {

// Cache component lookup at startup instead of doing this every frame
thisTransform = GetComponent< Transform >();
character = GetComponent< CharacterController >();
//joystick = GetComponent< CharacterController >();


// Move the character to the correct start position in the level, if one exists
GameObject spawn = GameObject.Find( "PlayerSpawn" );
if ( spawn )
thisTransform.position = spawn.transform.position;

moveTouchPad = new Joystick();
}


void OnEndGame()
{
// Disable joystick when the game ends
moveTouchPad.Disable();
jumpTouchPad.Disable();

// Don't allow any more control changes when the game ends
this.enabled = false;
}



// Update is called once per frame
void Update()
{
Vector3 movement = Vector3.zero;

// Apply movement from move joystick
if ( moveTouchPad.position.x > 0 )
movement = Vector3.right * forwardSpeed * moveTouchPad.position.x;
else
movement = Vector3.right * backwardSpeed * moveTouchPad.position.x;

// Check for jump
if ( character.isGrounded )
{
bool jump = false;
var touchPad = jumpTouchPad;

if ( !touchPad.IsFingerDown() )
canJump = true;

if ( canJump && touchPad.IsFingerDown() )
{
jump = true;
canJump = false;
}

if ( jump )
{
// Apply the current movement to launch velocity
velocity = character.velocity;
velocity.y = jumpSpeed;
}
}
else
{
// Apply gravity to our velocity to diminish it over time
velocity.y += Physics.gravity.y * Time.deltaTime;

// Adjust additional movement while in-air
movement.x *= inAirMultiplier;
// movement.z *= inAirMultiplier;
}

movement += velocity;
movement += Physics.gravity;
movement *= Time.deltaTime;

// Actually move the character
character.Move( movement );

if ( character.isGrounded )
// Remove any persistent velocity after landing
velocity = Vector3.zero;
}
}

YwJoystick.cs

using UnityEngine;
using System.Collections;

/**
 * File: YwJoystick.cs
 * Author: Chris Danielson of (monkeyprism.com)
 *
// USED TO BE: Joystick.js taken from Penelope iPhone Tutorial
//
// Joystick creates a movable joystick (via GUITexture) that
// handles touch input, taps, and phases. Dead zones can control
// where the joystick input gets picked up and can be normalized.
//
// Optionally, you can enable the touchPad property from the editor
// to treat this Joystick as a TouchPad. A TouchPad allows the finger
// to touch down at any point and it tracks the movement relatively
// without moving the graphic
*/

[RequireComponent(typeof(GUITexture))]

public class YwJoystick : MonoBehaviour
{
class Boundary {
public Vector2 min = Vector2.zero;
public Vector2 max = Vector2.zero;
}

private static YwJoystick[] joysticks; // A static collection of all joysticks
private static bool enumeratedJoysticks = false;
private static float tapTimeDelta = 0.3f; // Time allowed between taps

public bool touchPad;
public Vector2 position = Vector2.zero;
public Rect touchZone;
public Vector2 deadZone = Vector2.zero; // Control when position is output
public bool normalize = false; // Normalize output after the dead-zone?
public int tapCount;

private int lastFingerId = -1; // Finger last used for this joystick
private float tapTimeWindow; // How much time there is left for a tap to occur
private Vector2 fingerDownPos;
//private float fingerDownTime;
//private float firstDeltaTime = 0.5f;

private GUITexture gui;
private Rect defaultRect; // Default position / extents of the joystick graphic
private Boundary guiBoundary = new Boundary(); // Boundary for joystick graphic
private Vector2 guiTouchOffset; // Offset to apply to touch input
private Vector2 guiCenter; // Center of joystick

void Start() {
gui = (GUITexture)GetComponent(typeof(GUITexture));

defaultRect = gui.pixelInset;
defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // -  Screen.width * 0.5;
defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5;

transform.position = Vector3.zero;

if (touchPad) {
// If a texture has been assigned, then use the rect ferom the gui as our touchZone
if ( gui.texture )
touchZone = defaultRect;
} else {
guiTouchOffset.x = defaultRect.width * 0.5f;
guiTouchOffset.y = defaultRect.height * 0.5f;

// Cache the center of the GUI, since it doesn't change
guiCenter.x = defaultRect.x + guiTouchOffset.x;
guiCenter.y = defaultRect.y + guiTouchOffset.y;

// Let's build the GUI boundary, so we can clamp joystick movement
guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;
guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;
guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;
guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;
}
}

public Vector2 getGUICenter() {
return guiCenter;
}

void Disable() {
gameObject.active = false;
//enumeratedJoysticks = false;
}

private void ResetJoystick() {
gui.pixelInset = defaultRect;
lastFingerId = -1;
position = Vector2.zero;
fingerDownPos = Vector2.zero;
}

private bool IsFingerDown() {
return (lastFingerId != -1);
}

public void LatchedFinger(int fingerId) {
// If another joystick has latched this finger, then we must release it
if ( lastFingerId == fingerId )
ResetJoystick();
}

void Update() {
if (!enumeratedJoysticks) {
// Collect all joysticks in the game, so we can relay finger latching messages
joysticks = (YwJoystick[])FindObjectsOfType(typeof(YwJoystick));
enumeratedJoysticks = true;
}

int count = Input.touchCount;

if ( tapTimeWindow > 0 )
tapTimeWindow -= Time.deltaTime;
else
tapCount = 0;

if ( count == 0 )
ResetJoystick();
else
{
for(int i = 0; i < count; i++) {
Touch touch = Input.GetTouch(i);
Vector2 guiTouchPos = touch.position - guiTouchOffset;

bool shouldLatchFinger = false;
if (touchPad) {
if (touchZone.Contains(touch.position))
shouldLatchFinger = true;
}
else if (gui.HitTest(touch.position)) {
shouldLatchFinger = true;
}

// Latch the finger if this is a new touch
if (shouldLatchFinger && (lastFingerId == -1 || lastFingerId != touch.fingerId )) {

if (touchPad) {
//gui.color.a = 0.15;
lastFingerId = touch.fingerId;
//fingerDownPos = touch.position;
//fingerDownTime = Time.time;
}

lastFingerId = touch.fingerId;

// Accumulate taps if it is within the time window
if ( tapTimeWindow > 0 )
tapCount++;
else {
tapCount = 1;
tapTimeWindow = tapTimeDelta;
}

// Tell other joysticks we've latched this finger
//for (  j : Joystick in joysticks )
foreach (YwJoystick j in joysticks) {
if (j != this)
j.LatchedFinger( touch.fingerId );
}
}

if ( lastFingerId == touch.fingerId ) {
// Override the tap count with what the iPhone SDK reports if it is greater
// This is a workaround, since the iPhone SDK does not currently track taps
// for multiple touches
if ( touch.tapCount > tapCount )
tapCount = touch.tapCount;

if ( touchPad ) {
// For a touchpad, let's just set the position directly based on distance from initial touchdown
position.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 );
position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 );
} else {
// Change the location of the joystick graphic to match where the touch is
Rect r = gui.pixelInset;
r.x =  Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x );
r.y =  Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y );
gui.pixelInset = r;
}

if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
ResetJoystick();
}
}
}

if (!touchPad) {
// Get a value between -1 and 1 based on the joystick graphic location
position.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x;
position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y;
}

// Adjust for dead zone
var absoluteX = Mathf.Abs( position.x );
var absoluteY = Mathf.Abs( position.y );

if (absoluteX < deadZone.x) {
// Report the joystick as being at the center if it is within the dead zone
position.x = 0;
}
else if (normalize) {
// Rescale the output after taking the dead zone into account
position.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x );
}

if (absoluteY < deadZone.y) {
// Report the joystick as being at the center if it is within the dead zone
position.y = 0;
}
else if (normalize) {
// Rescale the output after taking the dead zone into account
position.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y );
}

}

}