2011年8月31日 星期三

UNITY3D - 2D圖動畫工具


遊戲中常常會用到一些2D連續圖來做UI特效,但是UNITY 3D本身不支援GIF格式的檔案,基於這些需求而寫了以下這隻程式。
目前的功能有:
1.播放一次
2.循環播放
3.淡入
4.淡出
5.放大
6.縮小
7.上升
8.下降

變數功能:
aniplayers :動畫詳細設定
size:有幾段動畫要播放
aniTexture:放連續圖的位置,需依序放入。
playTime:這段動畫的播放時間長度
frequency:時間內播放次數(淡入、淡出、放大、縮小、上升、下降無作用)
playMode:播放模式(播放一次、循環播放、淡入、淡出、放大、縮小、上升、下降)
waitTime:播放後等待時間(循環播放的作用為多久循環一次)
offset:偏移量,放大、縮小、上升、下降的依據
sync:同步,勾選後會跟下一段動畫同步播放
destroy:動畫播放完是否銷毀此GameObject

注意事項:
若勾選destroy時,至少要有一段動畫不能勾選sync

=======================================================================

enum AniPlayMode {PlayOnce,PlayCycle,FadeIn,FadeOut,Magnify,Minify,Up,Down};
class ANIPLAYER {
var aniTexture : Texture[];
@HideInInspector var startTime : float;
var playTime : float;
var frequency : int;
var playMode : AniPlayMode;
var waitTime : float;
var offset : float;
var sync : boolean;
}

var aniplayers : ANIPLAYER[];
var destroy : boolean;

@script RequireComponent (GUITexture)

function OnEnable () {
Play();
}

function Play () {
for(var aniplayer : ANIPLAYER in aniplayers)
{
if(aniplayer.playMode == AniPlayMode.PlayOnce)
{
if(aniplayer.sync)
PlayOnce(aniplayer);
else
yield PlayOnce(aniplayer);
}
else if(aniplayer.playMode == AniPlayMode.PlayCycle)
{
if(aniplayer.sync)
PlayCycle(aniplayer);
else
yield PlayCycle(aniplayer);
}
else if(aniplayer.playMode == AniPlayMode.FadeIn)
{
if(aniplayer.sync)
FadeIn(aniplayer);
else
yield FadeIn(aniplayer);
}
else if(aniplayer.playMode == AniPlayMode.FadeOut)
{
if(aniplayer.sync)
FadeOut(aniplayer);
else
yield FadeOut(aniplayer);
}
else if(aniplayer.playMode == AniPlayMode.Magnify)
{
if(aniplayer.sync)
Magnify(aniplayer);
else
yield Magnify(aniplayer);
}
else if(aniplayer.playMode == AniPlayMode.Minify)
{
if(aniplayer.sync)
Minify(aniplayer);
else
yield Minify(aniplayer);
}
else if(aniplayer.playMode == AniPlayMode.Up)
{
if(aniplayer.sync)
Up(aniplayer);
else
yield Up(aniplayer);
}
else if(aniplayer.playMode == AniPlayMode.Down)
{
if(aniplayer.sync)
Down(aniplayer);
else
yield Down(aniplayer);
}
}
if(destroy)
{
Destroy(gameObject);
}
}

function PlayOnce (aniplayer : ANIPLAYER) {
var index : int;
aniplayer.startTime = 0.0f;
while(aniplayer.startTime <= aniplayer.playTime)
{
index = (aniplayer.startTime * (aniplayer.aniTexture.Length / aniplayer.playTime) * aniplayer.frequency) % aniplayer.aniTexture.Length;
guiTexture.texture = aniplayer.aniTexture[index];
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
}

function PlayCycle (aniplayer : ANIPLAYER) {
var index : int;
aniplayer.startTime = 0.0f;
while(true)
{
while(aniplayer.startTime <= aniplayer.playTime)
{
index = (aniplayer.startTime * (aniplayer.aniTexture.Length / aniplayer.playTime) * aniplayer.frequency) % aniplayer.aniTexture.Length;
guiTexture.texture = aniplayer.aniTexture[index];
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
aniplayer.startTime = 0.0f;
}
}

function FadeIn (aniplayer : ANIPLAYER) {
aniplayer.startTime = 0.0f;
guiTexture.color.a = 0;
while(aniplayer.startTime <= aniplayer.playTime)
{
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
guiTexture.color.a = guiTexture.color.a + (Time.deltaTime / aniplayer.playTime);
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
}

function FadeOut (aniplayer : ANIPLAYER) {
aniplayer.startTime = 0.0f;
while(aniplayer.startTime <= aniplayer.playTime)
{
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
guiTexture.color.a = guiTexture.color.a - (Time.deltaTime / aniplayer.playTime);
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
}

function Magnify (aniplayer : ANIPLAYER) {
var scale : float = guiTexture.pixelInset.width / guiTexture.pixelInset.height;
aniplayer.startTime = 0.0f;
while(aniplayer.startTime <= aniplayer.playTime)
{
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
guiTexture.pixelInset.width = guiTexture.pixelInset.width + Time.deltaTime * aniplayer.offset * scale;
guiTexture.pixelInset.height = guiTexture.pixelInset.height + Time.deltaTime * aniplayer.offset;
guiTexture.pixelInset.x = guiTexture.pixelInset.x - Time.deltaTime * aniplayer.offset * scale / 2;
guiTexture.pixelInset.y = guiTexture.pixelInset.y - Time.deltaTime * aniplayer.offset / 2;
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
}

function Minify (aniplayer : ANIPLAYER) {
var scale : float = guiTexture.pixelInset.width / guiTexture.pixelInset.height;
aniplayer.startTime = 0.0f;
while(aniplayer.startTime <= aniplayer.playTime)
{
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
guiTexture.pixelInset.width = guiTexture.pixelInset.width - Time.deltaTime * aniplayer.offset * scale;
guiTexture.pixelInset.height = guiTexture.pixelInset.height - Time.deltaTime * aniplayer.offset;
guiTexture.pixelInset.x = guiTexture.pixelInset.x + Time.deltaTime * aniplayer.offset * scale / 2;
guiTexture.pixelInset.y = guiTexture.pixelInset.y + Time.deltaTime * aniplayer.offset / 2;
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
}

function Up (aniplayer : ANIPLAYER) {
aniplayer.startTime = 0.0f;
while(aniplayer.startTime <= aniplayer.playTime)
{
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
guiTexture.pixelInset.y = guiTexture.pixelInset.y + Time.deltaTime * aniplayer.offset;
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
}

function Down (aniplayer : ANIPLAYER) {
aniplayer.startTime = 0.0f;
while(aniplayer.startTime <= aniplayer.playTime)
{
aniplayer.startTime = aniplayer.startTime + Time.deltaTime;
guiTexture.pixelInset.y = guiTexture.pixelInset.y - Time.deltaTime * aniplayer.offset;
yield;
}
yield WaitForSeconds(aniplayer.waitTime);
}

2011年7月24日 星期日

蚊語錄

記錄自己說過,且還不錯的觀念

經典遊戲之所以經典是因為它的獨特性
當延續好幾代都差不多或者看起來感覺都一樣,那它就爛掉了

2011年7月20日 星期三

UNITY3D - 圖片淡入淡出

圖片淡入淡出其實跟GameObject逐漸透明消失的做法類似
只要改圖片本身的透明度就好了
要記得一點是顏色跟透明度的值是(x/256)的float值,不要以為直接塞1~256的值就可以...

圖片淡入
=========================================================================
function Start ()
{
guiTexture.color.a = 0; //讓圖片一開始為透明
}

function Update ()
{
if(guiTexture.color.a < 1)
{
guiTexture.color.a = guiTexture.color.a + Time.deltaTime; //讓圖片隨時間變不透明
}
}


=========================================================================

畫面淡出
=========================================================================

function Start ()
{
guiTexture.color.a = 1; //讓圖片一開始為不透明
}

function Update ()
{
if(guiTexture.color.a < 1) 
{
guiTexture.color.a = guiTexture.color.a - Time.deltaTime; //讓圖片隨時間變透明
}
}

=========================================================================

2011年7月13日 星期三

UNITY3D - 連續貼圖

U3D不支援顯示gif檔案,但是我們可以利用程式來將一連串的靜態圖片顯示得跟動態圖片無異。
首先建立一個empty object然後加入下面component script。

=======================================================================
var aTexture : Texture[]; //靜態圖片組
var framePerSecond : int; //每秒播放張數
var x : int; //x軸位置(以pixel為單位)
var y : int; //y軸位置(以pixel為單位)
private var startTime : float;
function Start () {
    startTime = Time.time; //記錄開始時間,確保圖從第一張開始放。
}
function OnGUI () {
    var index : int = ((Time.time - startTime) * framePerSecond) % aTexture.Length;
    GUI.DrawTexture(Rect(x, y, aTexture[index].width, aTexture[index].height), aTexture[index], ScaleMode.StretchToFill, true, 0);
}

=======================================================================
加入component後將靜態圖按順序設給aTexture以及設定framePerSecond與XY軸就可以看到在設好的(x,y)上顯示靜態圖片組成的動畫了。

手機測試

測試手機版blogger效果...上課太無聊,如果效果不錯之後就上課寫教學好了。

2011年7月3日 星期日

UNITY3D - GameObject逐漸透明消失

private var startTime : float;
private var alpha : float = 255.0f;

function Start () {
startTime = Time.time;
}

function Update () {
    if((Time.time - startTime) > 5)
    {
    var render = gameObject.GetComponentInChildren(Renderer);
    alpha = alpha - 10.0f;
    render.material.color.a = alpha / 255.0f;
    if(render.material.color.a <= 0)
    Destroy(gameObject);
    }
}
用處:用在怪被打死後逐漸消失。

以上程式功能為物件產生出來後經過5秒,然後將render的透明度逐漸遞減,當透明度低於0則清除此物件。注:Material的Shader必須用允許透明的Shader。

2011年6月30日 星期四

UNITY3D - 畫面震動效果

遊戲設計其實跟電影拍攝的概念很類似,構成電影最基本的元素是導演、攝影師、劇本、演員,而構成遊戲的最基本元素是鏡頭(導演、攝影師)、角色與NPC設定(劇本、演員)。

角色與NPC設定屬於控制與AI的設計,有賴於程設的構思去完善。相信很多人都會忽略鏡頭的重要性,但其實鏡頭就如同導演一般,要負責的東西多又繁雜且細膩。簡單來說...畫面上看到的東西都是鏡頭負責的(好像是廢話),舉凡玩家視角、遊戲介面、選單、畫面特效(震動、畫面變色)等等都是用鏡頭來呈現。

畫面震動的效果其實說穿了也沒什麼...不就是鏡頭晃一下就好了?以下是javascript code,附加到鏡頭上試試效果吧。
var shakePower : float = 2.0f; //設定震動的幅度
var shakeDelay : float = 0.05f; //設定震動的間隔時間

function UpDownShake () //上下震動
{
transform.Translate(Vector3.up * shakePower);
yield WaitForSeconds(shakeDelay);
transform.Translate(Vector3.up * -shakePower);
}

function LeftRightShake () //左右震動

{
transform.Translate(Vector3.right * -shakePower);
yield WaitForSeconds(shakeDelay);
transform.Translate(Vector3.right * shakePower);
}

function ForwardBackShake () //前後震動
{
transform.Translate(Vector3.forward * shakePower);
yield WaitForSeconds(shakeDelay);
transform.Translate(Vector3.forward * -shakePower);
}

function XRotateShake () //X軸晃動
{
transform.Rotate(Vector3.right * shakeAngle);
yield WaitForSeconds(shakeDelay);
transform.Rotate(Vector3.right * -shakeAngle);
}

function YRotateShake () //Y軸晃動
{
transform.Rotate(Vector3.up * shakeAngle);
yield WaitForSeconds(shakeDelay);
transform.Rotate(Vector3.up * -shakeAngle);
}

function ZRotateShake () //Z軸晃動
{
transform.Rotate(Vector3.foward * shakeAngle);
yield WaitForSeconds(shakeDelay);
transform.Rotate(Vector3.foward * -shakeAngle);
}

function Update ()
{
if(Input.GetKeyDown(KeyCode.Keypad1)) { StartCoroutine("UpDownShake"); }
if(Input.GetKeyDown(KeyCode.Keypad2)) { StartCoroutine("LeftRightShake"); }
if(Input.GetKeyDown(KeyCode.Keypad3)) { StartCoroutine("ForwardBackShake"); }
if(Input.GetKeyDown(KeyCode.Keypad4)) { StartCoroutine("XRotateShake"); }
if(Input.GetKeyDown(KeyCode.Keypad5)) { StartCoroutine("YRotateShake"); }
if(Input.GetKeyDown(KeyCode.Keypad6)) { StartCoroutine("YRotateShake"); }
}