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 );
}

}

}

SidescrollControl.js

// SidescrollControl creates a 2D control scheme where the left
// pad is used to move the character, and the right pad is used
// to make the character jump.
//////////////////////////////////////////////////////////////

#pragma strict

@script RequireComponent( CharacterController ) //캐릭터 콘트롤러를 쓰겠다.

// This script must be attached to a GameObject that has a CharacterController
var moveTouchPad : Joystick; // 조이스틱 스크립트를 담는다. gui 텍스쳐 포함
var jumpTouchPad : Joystick;

var forwardSpeed : float = 4;  // 우측
var backwardSpeed : float = 4;  // 좌측
var jumpSpeed : float = 16;  // 점프 
var inAirMultiplier : float = 0.25; // 공중 에서... // Limiter for ground speed while jumping

private var thisTransform : Transform;  // 트랜스폼을 변수에 담기 위해..
private var character : CharacterController; 
private var velocity : Vector3; // Used for continuing momentum while in air
private var canJump = true; // 점프 가능한지

function Start()
{
// Cache component lookup at startup instead of doing this every frame
thisTransform = GetComponent( Transform );  // 트랜스폼을 담는다.
character = GetComponent( CharacterController );  // 캐릭터 콘트롤러를 담는다.

// Move the character to the correct start position in the level, if one exists
var spawn = GameObject.Find( "PlayerSpawn" );  // 플래이어 되살아나는 지점?
if ( spawn )
thisTransform.position = spawn.transform.position;  // 뭘까?
}

function 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;   // 몰라..
}

function Update()
{
var 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 )  // 땅에 닿으면 
{
var 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;  // y값에 힘을 준다. 
}
}
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;
}

2013년 6월 12일 수요일

hp bar(2/2) - 그림 붙이기







아래는 게임에 사용될 바 이미지 입니다.
위에 것은
barTexture.png 이고 아래 것은 bgbarTexture.png 입니다.





-----------------------------------------------------
using UnityEngine;

using System.Collections;

public class ywplayerbar : MonoBehaviour {
public float maxBar = 100.0f;
public float justBar = 100.0f;

public Texture2D barTexture;
public Texture2D bgbarTexture;

public float barLength;

float bgjustBar = 100.0f;
float bgbarLength;
//float bgbarheight;

// Use this for initialization
void Start () {
barLength = Screen.width /2; // 바의 유니티 상 크기
bgbarLength = Screen.width /2; // 바 외곽의 유니티상...
}

// Update is called once per frame
void Update () {
AddjustCurrentBar(-3); // 1초에 얼마씩 줄일 것인지....

}

void OnGUI(){
//simplemode = 세가지 제공.. 그중 아래는 사간 화면 꽉 제운것...  true = 알파 브랜딩 오케이
GUI.DrawTexture(new Rect(13,10, barLength, 30), barTexture, ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(10,10, bgbarLength, 30), bgbarTexture, ScaleMode.StretchToFill, true, 0.0F);


// 박스로 작업한것에서.... 위에 드로우 텍스쳐로 바꾼 것은... 그림이 맘대로 제어되지 않았기 때문입니다.
//GUI.Box(new Rect(10,10,bgbarLength,20),bgbarTexture);
//GUI.Box(new Rect(10,10,barLength,20),barTexture);

}

public void AddjustCurrentBar(float adj){

justBar += adj * Time.deltaTime; // 1초에 얼마씩 줄일것인지.... 하는 변수

if(justBar<0) // 현재가 0보다 작으면...
justBar =0;
if(justBar>maxBar) // 현재가 맥스보다 크면..
justBar=maxBar; // 둘은 동일...
if(maxBar<1) // 맥스가 1보다 작으면...
maxBar=1;


barLength = (Screen.width/2)*(justBar/(float)maxBar);
// 빠지는 수치만큼 줄여나간다...
// 원래 크기에서...

}


}


생각보다 어려웟다는... 별다른 자료도 없고...
도데체 박스로 만들어 놓거나...

갭슐만 만든 예제는 결국 더 고민하게 만든다는...




hp bar(1/2) - 기본

using UnityEngine;
using System.Collections;

public class ywplayerbar : MonoBehaviour {
public float maxBar = 100.0f;
public float justBar = 100.0f;
public float bgjustBar = 100.0f;
public float barLength;
public float bgbarLength;

// Use this for initialization
void Start () {
barLength = Screen.width /2;
bgbarLength = Screen.width /2;
}

// Update is called once per frame
void Update () {
AddjustCurrentBar(-3);

}

void OnGUI(){

GUI.Box(new Rect(10,10,barLength,20),justBar + "/"+ maxBar);
GUI.Box(new Rect(10,10,bgbarLength,20),bgjustBar + "/"+ maxBar);
}

public void AddjustCurrentBar(float adj){

justBar += adj * Time.deltaTime;

if(justBar<0)
justBar =0;
if(justBar>maxBar)
justBar=maxBar;
if(maxBar<1)
maxBar=1;


barLength = (Screen.width/2)*(justBar/(float)maxBar);


}


}

unity3d 중요 팁

1) 백 버튼... 처리

if(Input.GetKeyDown(KeyCode.Escape)){ // 백버튼이 눌리면


}


2) 시간 경과 처리
var gameLength : float; // 제한 시간 길이
private var elapsed : float =0; // 체크 시간

elapsed += Time.deltaTime; // 체크 시간에 시간을 더한다. 제한시간보다 커지면 씬 전환..
if(elapsed >=gameLength){

GameController.SendMessage("PlayScene",1);
}

3) 터치하면

if(Input.touches.Length>0){

GameController.SendMessage("PlayScene",2);


}


4) 오브젝트 간에 이동을 동일하게...
var player : GameObject; // 플레이어를 담고
var pixcamera : float; // 카메라 영점을 맞춘다..

스타트 함수나... 업데이트 함수에..
var playerposition = player.transform; // 플레이어 트랜스폼을
var move = playerposition.position.y + pixcamera; // 픽스카메라 만큼 위치를 보정

transform.position.y = move;  // 카메라와 캐릭터는 이제 같이 움직인다.


5) 효과
1. 안개
   Edit/ Renderer Setting/ Fog
   
2. 바람 설정
GameObject>Create Other> WindZone

3. 눈
 Standard Assets/Particles/ Misc/Light Snow


6) 플랫폼 체크 //안드로이드면?

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    void Example() {
        if (Application.platform == RuntimePlatform.Android)
            Debug.Log("Do something special here!");
        
    }
}










smoothfollow2d

using UnityEngine;
using System.Collections;

public class smoothfollow2d : MonoBehaviour {

public Transform target; 따라갈 타겟을 정한다.
public float petX; // 펫이 위치할 x값
public float petY;

private Transform thisTransform; // 자신의 트랜스폼을 담을 변수.
        public float smoothTime = 0.3F;  // 따라가는 속도
        private float Velocity = 0.0F; //평균 속도?
// Use this for initialization
void Start () {



thisTransform = transform; // 변수에 담아 퍼포먼스에 영향을 최소화
}

// Update is called once per frame
void Update () {


float newPositionX = Mathf.SmoothDamp(thisTransform.position.x, target.position.x+petX, ref Velocity, smoothTime);
float newPositionY = Mathf.SmoothDamp(thisTransform.position.y, target.position.y+petY, ref Velocity, smoothTime);
       
        thisTransform.position = new Vector3(newPositionX, newPositionY, thisTransform.position.z);



}
}

캐릭터 컨트롤러를 통한 이동... (2d 화면뷰에서는 사용할수 없다.)

using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]

public class cube : MonoBehaviour {
    public float speed = 6.0F;
    public float jumpSpeed = 8.0F;
    public float gravity = 20.0F;
    private Vector3 moveDirection = Vector3.zero;


    void Update() {
        CharacterController controller = GetComponent<CharacterController>(); // 캐릭터 콘트롤러 참조
        if (controller.isGrounded) { // 땅에 있으면
            moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); // 전후좌우 조정
            moveDirection = transform.TransformDirection(moveDirection); .. 축을 바꾼다. 월드 좌표로
            moveDirection *= speed;  // 움직임의 속도를 제어...
            if (Input.GetButton("Jump")) // 점프 버튼 누르면

                moveDirection.y = jumpSpeed;  // 해당 y값에 대입... 점프 한다.
           
        }
        moveDirection.y -= gravity * Time.deltaTime;  // y값에 조절 중력 가속도라고 보면 된다.
        controller.Move(moveDirection * Time.deltaTime);  // 콘트롤러는 이 모든 데이터를 참조하여 움직인다.. 시간 개념으로..
    }
}

캐릭터 콘트롤러...
이걸로 2D로 사용하려고 바보같은 짓을 했다..
일단 이건.. 중력값을 가지고 시작하는 것...

기본적으로 바닥이 있다는 전제하에 움직인다...
삽질 끝...

이런 간단한것들이... 괴롭힌다..

2013년 6월 11일 화요일

게임 제어 -


public enum GameState { playing, gameover }; // 게임 스테이트

public class GameControl : MonoBehaviour {

    public Transform platformPrefab; // 판떼기.. 이거 앞으로 막 쓸거.. 과일도 이것으로
    public static GameState gameState; // 현재 게임 상태

    private Transform playerTrans;  // 특정 트랜스 폼을 담기 위한 변수
    private float platformsSpawnedUpTo = 0.0f; // 얼마나 위에서 나타날 것인가?
    private ArrayList platforms; // 플랫폼 배열
    private float nextPlatformCheck = 0.0f;  // 담에 어디서 나타날 것인가?

 
void Awake () {
        playerTrans = GameObject.FindGameObjectWithTag("Player").transform; // 플레이어의 트랜스 폼을 찾는다.
        platforms = new ArrayList(); // 배열을 참조하고..

        SpawnPlatforms(25.0f);
        StartGame(); // 게임 시작


}

    void StartGame()
    {
        Time.timeScale = 1.0f;  // 게임진행
        gameState = GameState.playing; // 게임변수 변화
    }

    void GameOver()
    {
        Time.timeScale = 0.0f; //Pause the game
        gameState = GameState.gameover;
        GameGUI.SP.CheckHighscore();// 점수를 체크
    }

void Update () {
        //Do we need to spawn new platforms yet? (we do this every X meters we climb)
        float playerHeight = 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.
        float currentCameraHeight = transform.position.y; // 카메라에 스크립트 붙어 있음... 카메라 위치를 참조
        float newHeight = 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 = (int)playerHeight;
        }
}



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

        //Delete all platforms below us (save performance)
        for(int i = platforms.Count-1;i>=0;i--)
        {
            Transform 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);
    }


    void SpawnPlatforms(float upTo) // 플랫폼 생성 같은데..
    {
        float spawnHeight = platformsSpawnedUpTo; 이 변수를 참조하고
        while (spawnHeight <= upTo) //작거나 같으면
        {
            float x = Random.Range(-10.0f, 10.0f); // 생성될 플랫폼의 x 위치를 랜덤하게 추출하고
            Vector3 pos = new Vector3(x, spawnHeight, 12.0f); // x위치 받고 높이 받고 z값은 생각좀 해봐야 함...

            Transform plat = (Transform)Instantiate(platformPrefab, pos, Quaternion.identity);  // plat 변수에.. 플랫폼 프리팹을 ,위치를 담고.. 생성?
            platforms.Add(plat); 배열에 집어 넣네?

            spawnHeight += Random.Range(1.6f, 3.5f); // 높이 값으로 체크 다음번 생성... 안에 있는 수치만큼 랜덤 y값을 더해서...
        }
        platformsSpawnedUpTo = upTo; // 다시 새 위치를 받는다.
    }

}

따라 다니는 팻 - yw_followPet.cs

팻이 따라오게 만드는 스크립트.. 쓸데 없이 고생 했다는...

using UnityEngine;
using System.Collections;

public class yw_followPet : MonoBehaviour {

    public Transform target; // 따라갈 타겟의 트랜스 폼
 
    private float relativeHeigth = 1.0f; // 높이 즉 y값
    private float zDistance = -1.0f;// z값 나는 사실 필요 없었다.
    private float xDistance = 1.0f; // x값
    public float dampSpeed = 2;  // 따라가는 속도 짧으면 타겟과 같이 움직인다.


void Start(){

// 타겟의 트랜스 폼을 가져 왔으면.. 변수에 담는 것이 옳으나.. 좀 헤깔려셔 패스

}

    void Update () {
        Vector3 newPos = target.position + new Vector3(xDistance, relativeHeigth, -zDistance); // 타겟 포지선에 해당 위치를 더해.. 즉 타겟 주변에 위치할 위치를 담는다.. 일정의 거리를 구하는 방법
        transform.position = Vector3.Lerp(transform.position, newPos, Time.deltaTime*dampSpeed); //그 둘 사이의 값을 더해 보정한다. 이렇게 되면 멀어지면 따라간다.
}
}


smoothdamp로 해도 무관한다..