2015年8月26日 星期三

UNITY3D - 用程式更改animation關鍵影格 change animation clip property value by script

有時候我們會需要物件的移動數值是可調整的,但可能因為架構上大量使用mecanim(animator)導致難以改用程式去控制物件移動。
這時候我們可以用程式更改animator所讀取的animation clip,將裡面的關鍵影格資訊改成所需要的數值。
善加利用state machine加上可變動的animation,mecanim的使用彈性就更高了。

所用到的function : AnimatorOverrideControllerAnimationClip.SetCurveAnimationClip.AddEvent

AnimationClip.SetCurve只會新增或蓋掉原本clip中有設定的property,要刪除某個property則在第四個參數(AnimationCurve)傳入null即可。

※注意,AnimationClip.SetCurve只在Editor上有效!

Runtime會更改專案中animation clip的寫法
//Change transform.localPosition.x move 0~100
//Change sprite.color.a 1~0
//Add event call Ready and pass parameter on 1sec
//gameObject structure:  gameObject:transform
//                           |
//                           --- child:SpriteRenderer
void ChangeAnimCurve () {
    Animator _animator = GetComponent();
    AnimatorOverrideController myOverrideController = new AnimatorOverrideController();
    myOverrideController.runtimeAnimatorController = _animator.runtimeAnimatorController;
    AnimationClip clip = myOverrideController["clipname"];
    clip.SetCurve("", typeof(Transform), "localPosition.x", new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 100f)));
    clip.SetCurve("child", typeof(SpriteRenderer), "m_Color.a", new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0f)));
    AnimationEvent evt = new AnimationEvent ();
    evt.functionName = "Ready";
    evt.intParameter = 1;
    evt.time = 1f; //make sure there got a keyframe
    clip.AddEvent (evt); //events added with AddEvent will only persist until play mode is exited of player is quit.
    _animator.runtimeAnimatorController = myOverrideController;
}




不更改專案中animation clip的寫法
//Change transform.localPosition.x move 0~100
//Change sprite.color.a 1~0
//Add event call Ready and pass parameter on 1sec
//gameObject structure:  gameObject:transform
//                           |
//                           --- child:SpriteRenderer
void ChangeAnimCurve () {
    Animator _animator = GetComponent();
    AnimatorOverrideController myOverrideController = new AnimatorOverrideController();
    myOverrideController.runtimeAnimatorController = _animator.runtimeAnimatorController;
    AnimationClip clip = new AnimationClip();
    clip.SetCurve("", typeof(Transform), "localPosition.x", new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 100f)));
    clip.SetCurve("child", typeof(SpriteRenderer), "m_Color.a", new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0f)));
    AnimationEvent evt = new AnimationEvent ();
    evt.functionName = "Ready";
    evt.intParameter = 1;
    evt.time = 1f; //make sure there got a keyframe
    clip.AddEvent (evt); //events added with AddEvent will only persist until play mode is exited of player is quit.
    myOverrideController["clipname"] = clip;
    _animator.runtimeAnimatorController = myOverrideController;
}

2015年6月9日 星期二

遊戲探討 — FPS/TPS射擊遊戲準心設計

因為眼力不好所以很少玩射擊遊戲,但最近有在進行射擊相關的遊戲開發,就來研究一下射擊遊戲的"眉角"。

射擊遊戲一般都有準心輔助玩家瞄準目標物;跟現實射擊類似,由視角槍口目標物三點成三角形,子彈在一定距離下才會準確命中目標物。


而遊戲為了體貼玩家,避免摸索這個有效距離,會設計成以準心對到的物體為有效距離再以槍口倒推這個三角形(實做上是以準心射出射線,再以射線終點當目標點,子彈從槍口朝目標點移動)
目標點近時
(這畫面視角不好畫出準心、目標物、槍口的三角形,直角只是槍口跟目標物的交叉,與下圖做比較可發現三角形的不同)

目標點遠時


但這有個問題是連射並且目標點改變(物體移動或消失)狀況下,會發現子彈軌跡改變,下兩張圖準心接近但可以很明顯看到軌跡不同。

為了放大這問題把準心移到角落,方塊為子彈圓球為槍口(起始點),
假設目標物較近時子彈軌跡

目標物消失或目標改為較後方的另一目標物時子彈軌跡


改善這問題的方法就是盡量拉近準心跟槍口的距離(縮小三角形面積,讓軌跡變化變小),連射時加上隨機偏差值(讓玩家忽略軌跡改變)。

也可能有別的改善方法,希望有人能提出來讓大家參考看看。

2014年1月20日 星期一

Unity 3D - Facebook SDK for Unity測試心得

Facebook推出SDK for Unity已經有段時間了(不過好像一直在beta版?)...

之前的專案因為Facebook SDK還不見蹤影而使用了prime31的SocialNetwork plugin來開發,現在總算有閒可以來測測這東西了。

在設定上Facebook參考了(我覺得啦...)prime31的設定方法,也就是用個asset檔來記錄設定,但Facebook做得更好的是在Unity介面上只要設定好Facebook App Id就幾乎大功告成了,其他需要輸入到Facebook介面上的資料也很貼心的整理好等著複製,甚至貼心到連Debug Android Key Hash也抓好了!

但發生了件令人費解的事情是Web版可以正常登入Facebook帳號也可以發文章,偏偏Android卻怎樣也無法登入...

查了許久才發現Facebook SDK自動生成的AndroidManifest檔案裡面activity android:name="com.unity3d.player.UnityPlayerNativeActivity"沒有被替換成com.facebook.unity.FBUnityPlayerActivity,只要修改好這點就可以正常使用無誤了。

2014年1月16日 星期四

UNITY3D - Time.timeScale

在遊戲中常會用到遊戲暫停的功能,Unity也提供了相關的功能就是將Time.timeScale設0。
但相信很多人會搞不清楚Time.timeScale會影響哪些東西,以下就來列一下會被Time.timeScale影響的部分。

1.FixedUpdate - 官方文件也聲明了Time.timeScale爲0時FixedUpdate不會被呼叫。
2.Rigidbody - Rigidbody的物理運算跟FixedUpdate有連帶關係,自然也就不會動作。
3.Time.time, Time.deltaTime, Time.fixedDeltaTime這些跟timeScale息息相關的數值也一樣逃不了,Time.time會停止、deltaTime會變0。
4.Animation - 非常依賴time的功能當然也就不會動了。
5.WaitForSeconds - 一樣是依賴time來做運算處理,那就一樣會停止運作。
6.WaitForFixedUpdate - FixedUpdate都不動了,那自然這也會停止運作了。

2013年11月14日 星期四

UNITY3D - Unity遊戲開發基礎Q&A

因為換工作交接的關係,才讓我意識到一般的程式設計人員要理解Unity有蠻大的障礙,如果有開發過遊戲或許還好一點,但如果只開發過一般應用程式的話就幾乎要重新理解觀念了。

Q1.Unity開發的程式進入點是什麼?
A1.Unity並沒有所謂的主程式進入點,遊戲以“場景”為一個主體,並且“場景”中有多個“遊戲物件”,每個“遊戲物件”內有一或多個“行為元件”。“行為元件”內才有所謂的起始進入點Awake,但要注意的是除非有經過設定每個“行為元件”的執行順序,不然在執行時“行為元件”的執行順序是不一定的。

Q2.寫好的Class怎麼使用呢?
A2.Unity內新增的程式檔案預設都會繼承MonoBehaviour,只要繼承MonoBehaviour就可以將這程式附加到“遊戲物件”上成為“行為元件”。只有在場景中的行為元件上的AwakeStart...等等MonoBehaviour的函式才會被執行。

Q3.MonoBehaviour有哪些函式?在什麼情況下用?
A3.通常最常用的是
AwakeStartUpdate還有碰撞相關的OnCollisionEnterOnTriggerEnterAwake 、Start用於初始化(Awake會比Start先執行),Update是每個Frame會執行一次,其他詳細的MonoBehaviour請參閱這裡

Q4.Frame是什麼意思?
A4.在遊戲中是指程式執行頻率也就是FPS(是Frames Per Second不是First Person Shooter),意味著一秒鐘執行多少個Frame。

Q5.有辦法知道每Frame的實際執行耗時嗎?
A5.Unity有提供Time.deltaTime可以取得每Frame實際耗時。

Q6.設定行為元件的enable?
A6.在Unity Editor上行為元件的勾選可以控制元件的enable,或者也可以在程式中直接設定enable。enable會影響StartUpdate是否執行,使用時需多加注意。

Q7.遊戲物件的父子物件關係?
A7.遊戲物件可以跟別的遊戲物件成為父子物件關係,子物件會隨著父物件移動。

Q8.如何執行別的行為元件的函式?
A8.1)宣告一該行為元件型態變數,并在Unity Editor上將指定的行為元件設定到變數上,或者是在程式裡用Object.FindObjectOfType(在別的遊戲物件上)、GetComponent(在本身的遊戲物件上)並執行函式。2)將該函式宣告為static,但並不建議此方法,除非是用在類似整個遊戲狀態管理上。3)使用Unity的SendMessage機制,SendMessage系列有三種,1.SendMessage(string methodName):對本身遊戲物件上的所有行為元件(不含父物件及子物件上的)通知執行跟methodName同名的函式;2.SendMessageUpwards(string methodName):對本身遊戲物件及父物件上的所有行為元件(不含子物件上的)通知執行跟methodName同名的函式;3.BroadcastMessage(string methodName):對本身遊戲物件及子物件上的所有行為元件(不含父物件上的)通知執行跟methodName同名的函式。

Q9.Prefab機制?
A9.當“遊戲物件”綁上很多“行為元件”後,要怎麼去重複利用這個“遊戲物件”呢?於是Prefab機制就出現了,將設定好的“遊戲物件”拖曳到Project View就可以將它變成Prefab。只要將Prefab拖曳到場景中就可以變成已經設定好的“遊戲物件”,這裡要注意的是Prefab跟產生出來的“遊戲物件”有父子關係。只要Prefab上的設定一更動,所有由此Prefab產生的“遊戲物件”都會更動,但如果是“遊戲物件”更動的話是不會影響Prefab及其它“遊戲物件”。 跟Prefab有關係的“遊戲物件”上會出現這些控制按鈕,Select可以讓你找到此物件的Prefab;Revert會讓此物件的設定回復得跟Prefab一樣;Apply會將此物件的設定覆蓋回Prefab,連帶的會更動到由此Prefab產生出來的其他“遊戲物件”。最後還要注意的是,更動“遊戲物件”上“行為元件”的設定值將會使這設定值被設立旗標(設定值會變粗體),表示此設定值跟Prefab脫鉤,Prefab更動也不會影響到此設定值


之後有想到什麼再補充上去吧...

2013年8月6日 星期二

福島GameJam 2013作品-神蹟之躍



http://fgj.igda.jp/dokuwiki/doku.php?id=team%3Ataipeiiii_c

這次在福島GameJam做出來的小小作品,因為時間只有30小時,所以隊名叫30hr應援團。

這次的主題是Jump,於是做了個類跳棋的遊戲。




遊戲目的是讓左下方出現的災民移動到右上方的出口

操作方式是是用滑鼠點擊可以交換同一行或同一列的地形,其中有些地形是無法交換的。

按Space Bar後再點擊地形可強制把地形更換。

詳細地形功能及地形變化表請參考網頁。

另,本作品將會在TGS東京電玩展的Indie Corner展出,請有到TGS的朋友幫忙拍個照讓我做個紀念,謝謝!

2013年2月4日 星期一

Global Game Jam讓你的心跳起來!

  自從去年2012年在Google+上看到有人分享參加MIT Game Jam的心得文章之後,心裡就一直想找機會參加這類活動,但去年12月的Ludum Dare又因為正好公司所作的遊戲正忙著收尾準備上架導致沒辦法參加(雖然事後還是忍不住自己做了個應景的世界末日遊戲http://dl.dropbox.com/u/26037476/Wasabi/Wasabi.html)。

  於是看到Global Game Jam的活動資訊時,不管三七二十一就填好報名資料送交了。一些同事知道我報名參加後問我說為什麼我要參加這種沒有名次沒有獎品的活動(還要爆肝...),當下我是無言以對,但事後想來也許就是因為那股熱血吧?我想要知道自己的實力、想知道這個世界有多廣、想見識更多高手,就如同這次的作品想表達的:就算是行尸走肉,只要找到目標就可以讓你的心臟再次跳動!(肝可以爆,但是請爆在你認為值得的事物上。)

  這次的主題很棒,就只有聽到心跳聲,但是卻可以讓人作出各種聯想。晚餐過後我們與遲到的成員會合並展開討論,一開始我提出了根據心跳聲的狀況來移動的遊戲,但是為了不浪費我們組的美術就捨棄了,我們從最直觀的方向入手,心跳聲來自心臟,再衍生到文明病,是一款玩家必須消除進入心臟有害物質的遊戲。 

  但還沒定案時,Ingrid讓我們看了一款雙螢幕的flash遊戲(我忘了名字 囧rz),大家討論後覺得切兩個螢幕可以讓玩家有緊張感可以採用,於是其中一個螢幕就變成心臟了(?),心臟是提供給人動力的來源,但我們又想要跟常識相反,另一個螢幕就變成殭屍在跑了XD。為了給殭屍跑的理由,原本是讓他對一個女生一見鍾情所以追著她跑,但後來又惡搞成是為了還那個女生錢包XD,再後來為了讓女生穿過障礙物不會顯得突兀所以她變成女鬼了(這是什麼發展XD),雖然最後我還是幫她寫了簡單的AI但是她已經沒辦法復活成人了XD。

  在最後一刻我們終於順利把作品完成,實在是非常感謝大家的努力!

感謝

企劃:Kinan
美術LightAngel (連續三天搬電腦主機來往住家與會場,超猛!)
主程式:Vincent Sai (感謝自己選擇把肝爆在GGJ)
場景程式:伍小韻
程式:小熊、劉柏賢

  雖然三天下來我真是體力耗盡,回到家也只是拼命的睡,但有一點可以肯定的是,下次我還是會參加!

作品頁面連結:http://globalgamejam.org/2013/hopping-dead