2014年11月23日 星期日

[Unity] Platform & Build


Unity可以開發和輸出到很多平台的遊戲

但是電腦很明顯和滑鼠操作模式不同,那關於同一種遊戲怎麼開發呢?


C#腳本:

可以使用定義(define)去為不同平台做區隔,好像會只有在輸出此平台時才會compile這段

ex:
#if UNITY_WEBPLAYER
        //do what only on webplayer
 #endif


UnityScript腳本:

沒有定義,但可以用if去判斷

ex:
if (Application.platform == RuntimePlatform.Android )
{
        //do what only on Android
}


至於操作方法手機觸控等,Unity也有方便的存取方法這邊先不提了



輸出部分幾個心得:

1.Player Setting裡,Bundle Identifier不同,會使手機OS判斷APP為不同APP
所以如果手機上想要有同專案但不同版本的輸出,就是修改Bundle Identifier去實現

2.Android 可以輸出 android 專案 或直接輸出安裝檔

3.IOS 輸出必須要有 MAC電腦、Xcode工具、和IOS開發者付費帳號


但關於輸出Unity官方最近似乎再做很神的東西

Cloud Build:
http://unity3d.com/unity/cloud-build


要不是Pro一次要至少買一年
我真的就馬上要催錢下去了

Unity的領導團隊我還沒研究是誰
不過真的是我會感到害怕和五體投地的人物^ ^|||

[Unity] Facebook SDK


竟然離上次發文快一個半月了= =
這陣子比較主要的收穫首先大概就是FB和Unity的結合應用吧


開發網站教學:
https://developers.facebook.com/docs/unity/getting-started/canvas


一言以蔽之,開發網站的說明影片,好好看完
去載範例專案,上手就差不多了


剩下會遇到的問題主要是
1.FB APP 除了

LOGIN PERMISSIONS
email
Provides access to the person's primary email address. This permission is approved by default.
public_profile
Provides access to a person's basic information, including first name, last name, profile picture, gender and age range. This permission is approved by default.
user_friends
Provides access to a person's list of friends that also use your app. This permission is approved by default.

以上幾種權限資料,其他資料想取得都要另外申請權限,審核過程還想當嚴謹= =|||

這邊要另外注意user_friends 能取得的好友,只有已授權給你FB APP的好友


2.如果想未經核准就使用需要權限的功能,就只能將使用者加入test uesr之類的

3.結論: 目前覺得用來做登入功能算很方便,但要進行甚麼社交分析就會非常麻飯

2014年10月12日 星期日

[Unity] MonoBehaviour,腳本類別

一直提到可以幫物件附加自己建立的腳本(Script),而MonoBehaviour就是所以腳本必須繼承的父類別,定義了每個腳本應該有個基本變數和函數

其中腳本可以用三種語言撰寫C# and Boo 和 UnityScript

using UnityEngine;
using System.Collections;

public class MainPlayer : MonoBehaviour {
    public string myName;
    
    // Use this for initialization
    void Start () {
        Debug.Log("I am alive and my name is " + myName);
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}
這是C# 的簡單範例,Boo(我不知道這是甚麼)好像形式也類似,都要自行引用UnityEngine等,還要宣告類別去繼承MonoBehaviour
另外一種是UnityScript,會自動完成繼承和引用,相比之下就精簡很多
#pragma strict var myName: String ; function Start () { Debug.Log("I am alive and my name is " + myName); }function Update () {}

UnityScript在語法上其實跟JavaScript一模一樣,連檔案格式都是JS,但是因為多了很多Unity自己增加的類別和新功能,所以其實之前就覺得要說是JavaScript又怪怪的,又是因為寫文章查官網才發現原來他們自己也稱呼成UnityScript


關於腳本怎麼用,還是建議找會的人親自教最快,其次就是看圖文並茂的書或官網(http://docs.unity3d.com/Manual/ScriptingConcepts.html),這邊就不多解釋了

一樣只講比較心得和自己之前沒注意的地方
就是update系列function的應用 (如果還沒用過腳本,但還是想先了解,請點上方連結)

update function基本上都會根據硬體和需求有一個自己的更新頻率,並在遊戲期間不斷被執行
因此例如code

function Update () { transform.Translate(Vector3(0, 0, 1) * Time.deltaTime);}

遊戲執行時就會不斷執行transform.Translate(Vector3(0, 0, 1) * Time.deltaTime)使物件持續前進
這裡就可以解釋Time.deltaTime了,如上面所說,update有自己的更新頻率,並且這種更新頻率其實對於遊戲環境硬體或資源不同時,更新頻率並不會永遠一致
(假設Translate(Vector3(0, 0, 1)代表走一步,FPS30的環境一秒會有三十,FPS60的環境一秒會走60,造成同遊戲在不同環境和條件有速度感上的不同)


因此利用呼叫Time.deltaTime會回傳:  1秒 / (update更新頻率)
因此當Update的參數乘上Time.deltaTime,就會變成一秒的量 ,而成為一個不受FPS影響的值
(假設Translate(Vector3(0, 0, 1)代表走一步,FPS30的環境一秒會有三十步 * (1/30) = 一步,FPS60的環境一秒會走60 * (1/60) = 一步,使同遊戲在不同環境和條件的速度感一致)


而update的function有三種

1.Update: 就是最基本的update大部分的功能都會直接寫在這裡
2.FixedUpdate:由於物理引擎的計算和普通Update頻率不同,而FixedUpdate正是以物理引擎頻率為更新頻路的Update Function,因此跟物理特性有關的程式如: rigidbody.AddForce()等,會建議寫在FixedUpdate以取得比較精準的結果
3.LateUpdate: 在Update和FixedUpdate結束後被呼叫,LateUpdate主要用途是用來將輔助先先後順序的程式碼可以更好的被分開,官方舉例是攝影機要追隨物體移動,那好的設計是物體在Update裡計算完移動後,才在LateUpdate更新攝影機在物體後的位置


這邊真的蠻重要的
不然之前都傻傻的混在一起寫,平白浪費了很多資源,程式碼也容易冗長混亂^ ^|||

[Unity] Collider

官網教學:
http://docs.unity3d.com/Manual/CollidersOverview.html


因為官網沒有圖,這次就不貼介紹了,畢竟都英文的
所以就由我來直接解釋吧

Collider就是碰撞框
物件附上碰撞框屬性之後就會賦予它偵測與其他物件碰撞的範圍和能力
有了碰撞框才能做出例如地面、牆壁、砲彈等等,能阻礙或擊中物體的效果

而碰撞框有好幾種形狀
主要有長方形、球形、膠囊型、圓柱形,比較異類的有地形碰撞框、Wheel Collider 、Mesh Collider(不知怎翻譯才好),一個物件可以利用多個碰撞框組成複雜的碰撞框,這邊想知道詳情請點上方官方教學連結

A real-world Compound Collider setup


而碰撞框自身又有兩種類型
Trigger(觸發器)和非Trigger

在設計上觸發器類型的碰撞框通常用來做事件出發的應用(簡單來說就是用來偵測玩家或物件進入指定區域)

而非觸發器類型通常就是配合Rigidbody去實做物理現象的碰撞效果(兩顆球相撞)


觸發器碰撞過程會觸發
OnTriggerEnterOnTriggerEnter is called when the Collider other enters the trigger.
OnTriggerExitOnTriggerExit is called when the Collider other has stopped touching the trigger.
OnTriggerStayOnTriggerStay is called almost all the frames for every Collider other that is touching the trigger.
非觸發器碰撞會觸發
OnCollisionEnterOnCollisionEnter is called when this collider/rigidbody has begun touching another rigidbody/collider.
OnCollisionExitOnCollisionExit is called when this collider/rigidbody has stopped touching another rigidbody/collider.
OnCollisionStayOnCollisionStay is called once per frame for every collider/rigidbody that is touching rigidbody/collider.
而碰撞會不會發生其實還是有些條件的
以下是官方的碰撞發生表,不過這等到實際開始用Collider,已經有些實際上試用後的理解或困惑,再來看會比較看得懂^ ^|||

Collision detection occurs and messages are sent upon collision
Static ColliderRigidbody ColliderKinematic Rigidbody ColliderStatic Trigger ColliderRigidbody Trigger ColliderKinematic Rigidbody Trigger Collider
Static Collider Y    
Rigidbody ColliderYYY   
Kinematic Rigidbody Collider Y    
Static Trigger Collider      
Rigidbody Trigger Collider      
Kinematic Rigidbody Trigger Collider      
Trigger messages are sent upon collision
Static ColliderRigidbody ColliderKinematic Rigidbody ColliderStatic Trigger ColliderRigidbody Trigger ColliderKinematic Rigidbody Trigger Collider
Static Collider    YY
Rigidbody Collider   YYY
Kinematic Rigidbody Collider   YYY
Static Trigger Collider YY YY
Rigidbody Trigger ColliderYYYYYY
Kinematic Rigidbody Trigger ColliderYYYYYY
Rigidbodies

[Unity] Rigidbody

官網教學:

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

Rigidbody

SWITCH TO SCRIPTING
Rigidbodies enable your GameObjects to act under the control of physics. The Rigidbody can receive forces and torque to make your objects move in a realistic way. Any GameObject must contain a Rigidbody to be influenced by gravity, act under added forces via scripting, or interact with other objects through the NVIDIA PhysX physics engine.


Properties

Property:Function:
MassThe mass of the object (arbitrary units). You should not make masses more or less than 100 times that of other Rigidbodies.
DragHow much air resistance affects the object when moving from forces. 0 means no air resistance, and infinity makes the object stop moving immediately.
Angular DragHow much air resistance affects the object when rotating from torque. 0 means no air resistance. Note that you cannot make the object stop rotating just by setting its Angular Drag to infinity.
Use GravityIf enabled, the object is affected by gravity.
Is KinematicIf enabled, the object will not be driven by the physics engine, and can only be manipulated by its Transform. This is useful for moving platforms or if you want to animate a Rigidbody that has a HingeJoint attached.
InterpolateTry one of the options only if you are seeing jerkiness in your Rigidbody’s movement.
        NoneNo Interpolation is applied.
        InterpolateTransform is smoothed based on the Transform of the previous frame.
        ExtrapolateTransform is smoothed based on the estimated Transform of the next frame.
Collision DetectionUsed to prevent fast moving objects from passing through other objects without detecting collisions.
        DiscreteUse Discreet collision detection against all other colliders in the scene. Other colliders will use Discreet collision detection when testing for collision against it. Used for normal collisions (This is the default value).
        ContinuousUse Discrete collision detection against dynamic colliders (with a rigidbody) and continuous collision detection against static MeshColliders (without a rigidbody). Rigidbodies set to Continuous Dynamic will use continuous collision detection when testing for collision against this rigidbody. Other rigidbodies will use Discreet Collision detection. Used for objects which the Continuous Dynamic detection needs to collide with. (This has a big impact on physics performance, leave it set to Discrete, if you don’t have issues with collisions of fast objects)
        Continuous DynamicUse continuous collision detection against objects set to Continuous and Continuous Dynamic Collision. It will also use continuous collision detection against static MeshColliders (without a rigidbody). For all other colliders it uses discreet collision detection. Used for fast moving objects.
ConstraintsRestrictions on the Rigidbody’s motion:-
        Freeze PositionStops the Rigidbody moving in the world X, Y and Z axes selectively.
        Freeze RotationStops the Rigidbody rotating around the world X, Y and Z axes selectively.

Details

Rigidbodies allow your GameObjects to act under control of the physics engine. This opens the gateway to realistic collisions, varied types of joints, and other very cool behaviors. Manipulating your GameObjects by adding forces to a Rigidbody creates a very different feel and look than adjusting the Transform Componentdirectly. Generally, you shouldn’t manipulate the Rigidbody and the Transform of the same GameObject - only one or the other.
The biggest difference between manipulating the Transform versus the Rigidbody is the use of forces. Rigidbodies can receive forces and torque, but Transforms cannot. Transforms can be translated and rotated, but this is not the same as using physics. You’ll notice the distinct difference when you try it for yourself. Adding forces/torque to the Rigidbody will actually change the object’s position and rotation of the Transform component. This is why you should only be using one or the other. Changing the Transform while using physics could cause problems with collisions and other calculations.
Rigidbodies must be explicitly added to your GameObject before they will be affected by the physics engine. You can add a Rigidbody to your selected object from Components->Physics->Rigidbody in the menubar. Now your object is physics-ready; it will fall under gravity and can receive forces via scripting, but you may need to add a Collider or a Joint to get it to behave exactly how you want.
=================================================================
恩...為了寫文章才去官網找教學發現,果然我也該把官網好好讀一讀才對,我遺漏的關鍵知識實在太多了= =+
好,簡單來說如果希望一個遊戲物件(GameObject)有物理屬性,就要替他增加Rigidbody屬性
(Unity所有物件都是從基本的GameObject,預設只有Transform然後自行附加各種屬性和腳本,製作出符合自己要求的物件)。

有了Rigidbody屬性,物件就會擁有物理特性,像質量、速度、角動量等等
附加Collider之後也能和其他物件產生碰撞,Collider和碰撞會在下一篇文章介紹

這邊要講一個經驗上的重點
當一個有Rigidbody的物體要移動或旋轉
要用Rigidbody類別的AddForce()和AddTorque()去處理
雖然之前提到Transform也可以用其類別中的Translate()和Rotate()去做出移動和旋轉
但是最大的差異是Rigidbody的函數符合物理,是由物理引擎運算出連續的結果
但是Transform類別會製造無視物理的強制移動,以Translate()為例,會直接讓物件強制往前移動指定的單位,並且移動不是連續的,是"直接加上"移動的值,所以物件很可能會直接陷入牆裡,或穿過物體 (簡單來說Transform其實都不是連續移動或旋轉,是類似空間跳躍)

所以如果希望Rigidbody物件以符合物理現象的方式移動和旋轉
一定要用Rigidbody的函數,而不要直接使用Transform的函數

當然反過來向玩家視角的攝影機等
不用附加物理屬性也不用做符合物理的移動就直接使用Transform比較恰當

這個經驗太晚領悟,也太晚看官網教學的代價就是
我目前V2.1.0的遊戲,很多物件和NPC的移動幾乎都要大修了T^T
(之前看他們會陷牆或爬上峭壁還不以為意,以為是真的可以這樣,後來才發現自己錯得很嚴重= =)

2014年10月11日 星期六

[Unity] Transform

先直接複製官網教學
http://docs.unity3d.com/Manual/class-Transform.html
=====================================================
The Transform component determines the PositionRotation, and Scale of each object in the scene. Every GameObject has a Transform.

Properties

Property:Function:
PositionPosition of the Transform in X, Y, and Z coordinates.
RotationRotation of the Transform around the X, Y, and Z axes, measured in degrees.
ScaleScale of the Transform along X, Y, and Z axes. Value “1” is the original size (size at which the object was imported).
The position, rotation and scale values of a Transform are measured relative to the Transform’s parent. If the Transform has no parent, the properties are measured in world space.
=====================================================
經驗上來說,Transform就是Unity最重要的屬性了
因為他代表一個物件在空間中的位置,旋轉量,和大小
這邊解釋一下官網說明的最後一句
Unity的物件是可以有親子關係的,有點像是人坐在車裡
因此物件的transform數值基本上都是以父物件為0點的數值 (做進車裡後,就只管自己坐在車子的什麼位置)
也因此Unity裡只要父物件移動,子物件也會跟著移動 (車子開,坐在裡面的人就被載著走了)

最後要額外解釋一下rotation
基本上Unity的position是用三個參數去表示x,y,z 程式中也會常常看到用一個名為Vector3的類別去建構三維變數(http://docs.unity3d.com/ScriptReference/Vector3.html
rotation是用Quaternion(http://docs.unity3d.com/ScriptReference/Quaternion.html)去儲存,Quaternion是一個有四維度(w,x,y,z)當變數的類別,但原則上不用去管wxyz的值,基本上由於難以理解官方文件也建議不要修改wxyz,因此如上圖實際上我們看到用三個維度的表示法叫做尤拉角(只是呈現出來是這樣,實際上還是用Quaternion儲存)
不過Unity的尤拉角跟一般數學上的尤拉角表示法也不太一樣,Unity的尤拉角很容易理解,呈現旋轉量是"先延自己的Y軸旋轉y度,再延自己的X軸選轉x度,最後再延自己的Z軸選轉z度",但雖然理解起來容易,這種表示法卻讓人很難直覺的去修改旋轉量,所以要修改rotation真的就要善用transform和QuaternionAPI

大概一開始會搞錯的就只有這邊
剩下其實自己摸摸就很容易理解啦

接下來講一下transform的Script
http://docs.unity3d.com/ScriptReference/Transform.html
基本上官方API真的超強,每個變數或函數都會有範例

例如:
transform.Translate(Vector3(0, 0, 1) * Time.deltaTime);
就會讓transform延Z方向移動, 乘Time.deltaTime的理由之後的文章會解釋
這邊先重點看看transform的概念就好

2014年10月10日 星期五

[Unity] Unity優缺點分析

上一篇推銷有點跑題,這篇務實一點做重點優缺點分析吧


優:

1.界面操作很直覺,例如物件要當參數都用滑鼠直接拉就可以
2.物理引擎很完整,對物理現象的模擬和控制變得非常輕鬆
3.完成度非常高,幾乎對遊戲製作需要的功能都有特地設計過
不管環境是2D3D,PC,手機等平台,類型不管塔防動作FPS等遊戲都幾乎能用Unity製作
已經預設好很多現成模組,幾乎靠組合現成模組就能作到很多事
4.自定義腳本來增加遊戲程式也非常直覺和容易
5.輸出平台非常之廣:從Windows x86/64, Mac, Linux,甚至連Ios,Android都可以輸出,畢竟連黑莓機和windows8 APP Store等都支援了...
6.基本版免費 (當然付費版功能更強大)

缺:

1.功能強大的同時,本身是一款相當號資源的程式,電腦不夠好就會跑不順
強烈建議有SSD就安裝在SSD
2.註冊時選國家,目前還沒有Taiwan,所以我目前試選了個冰島
3.開發環境是英文,網站基本也是英文,不過網站雖然有大陸自己的中文翻譯
可是我還是覺的英文的比較容易看,畢竟用詞都不會太艱深,而且跟環境配合理解起來也比較直覺

[Unity] Unity介紹和心得

Unity是當初詩詩他們參加華碩體感比賽,我看到才開始接觸的
接觸之後真的覺得是,扯的誇張的遊戲引擎
以前用Flash作遊戲已經覺得很方便了,用了Unity之後才發現
我原本還像原始人鑽木取火

Unity的官網:
http://unity3d.com/

Unity官方的介紹手冊:
http://docs.unity3d.com/Manual/index.html


其實故意貼上介紹手冊真的是順便說明
他們網站真的做的超級完整
不管是技術文件(API)還是技術簡介,甚至專案範例和影片都很詳細並深入淺出
而且遊戲引擎本身操作上也非常直覺

一言以敝之就是非常容易上手(只有完全剛開始,還靠自己會覺得難)

加上推廣和普及率夠,坊間的書真的非常多
其中我特別推薦這本

書名:

Unity 3D遊戲設計實戰

http://findbook.tw/book/9789862767207/basic


我有個消遣就是去書局晃晃
但晃到目前真的就是這本書最好
入門夠詳細,但深度廣度也夠
有別於大部分的書,其實只有幾種入門技巧,卻用好多範例重複解釋

有興趣要借來看看的話
我和圖書館都有喔XD

新起點

好久沒發文,這週三(10/8)真的是對我充滿衝擊的一天
其實這陣子真的非常忙
除了腦中心和實驗室的程式要寫
真的幾乎所有時間都在準備專題決賽
幾乎每天都12點之後才離開實驗室,回家還會繼續弄到4,5點

可是我原本計畫決賽的時候
要用手勢辨識的技術來操縱投影片
還有找人和我用連線遊戲進行華麗又撒狗血的對戰
但我做不完
雖然我專題本身的完整性和完成度很高
可是對於決賽的表演我最後只能進行非常普通的投影片解說和DEMO影片

所以比賽完我一度非常沮喪
在自身的方面我真的覺得沒有遇到大困難
想用的技術學的會,程式寫的出來,就算卡關也不會卡太久
可是就是來不及完成心中想達到的標準

沒有偷懶 沒有鬆懈 沒打電動 沒睡多少
但離完成真的差好遠
遊戲雖然也只是要展示我研發的新型人機界面
但是想完成的遊戲機制,角色,音效等,其實也都還差很多

所以報告完的時候,其實真的是很沮喪
雖然我一直都知道,一個遊戲是企劃,美術,程式和音效四大元素組成
也知道我無法我一己之力和才能是無法做出我心中想的大型遊戲的
但我到專題決賽結束才真正認清這件事

其實再認清這件是的時候,就覺得專題競賽怎樣都好
可能在我單打獨鬥的時候其實就算輸了


但運氣真的很好
首先明明說10/13才公佈的,結果竟然當天下午就公佈
再來原因我想了很多,可能看我老,看我寂寞,或我專題本身完成度算高
(其實我到最後都搞不清楚理由)

但真的很開心竟然拿到特優
算被拯救了嗎XD?

不過好不容易認清的事實我會好好珍惜的
在繼續前進之前,我一定要找到夥伴

之前的我太禁不起挫折,一下子就放棄
嘴巴都說夥伴夥伴,但心裡根本還是只打算靠自己
這次不管失敗多少次,都一定要找到其他真的也想做遊戲的人!!

2014年9月11日 星期四


結果意外學會了Animator和Ragdoll讓原本很生硬的動作變得
很奇怪XD?

不過人模都能使用動畫真的是超大福音
看到會戰打成一團真的是很好笑

但最喜歡的還是把一坨人炸飛跟武將被圍毆吧
我擔心我可能心理變態=口=






2014年9月5日 星期五

弄了幾天總算有點雛型了
Unity真的是非常強悍的遊戲引擎
不過有些設定沒人教,又沒辦法看API就天悟的話
真的要稍微摸一下呢^ ^|||




2014年8月22日 星期五


誠摯的謝謝你One V
你是一隻非常優秀的手機
大學四年有你真是太好了

E8請多多指教啦^ ^


2014年8月20日 星期三



我要謝謝
所有對我的遊戲企劃
給予肯定和支持的人
謝謝你們
我會加油的^ ^

2014年7月29日 星期二

去年暑假做的遊戲

去年暑假為了搭配體敢做的遊戲,可惜後來覺得沒幾個關節的人物實在無法呈現體感的魅力就轉型了

但是做遊戲的日子好愉快,每天睡醒就想繼續寫Code哈哈哈

今年暑假要再做出一個超厲害的!!


====================說明============
冰人:
SXZC: 上下左右
R: 弓箭型態 長按是箭雨
T: 槍型態 長按是突進
Y: 錘型態 長按是集氣變大
5: 劍型態 長按是大劍斬

邪鬼:
鍵盤上下左右: 上下左右
數字鍵1: 氣功 集氣是氣功波
數字鍵2: 拳擊 集氣是突進
數字鍵3: 鐮刀 集氣是旋轉
數字鍵5: 召喚 集氣是召喚黑龍

https://dl.dropboxusercontent.com/s/htyldnvcru0zckr/main.swf

2014年7月28日 星期一

腦中心APP



之前因為一直照著寫好,又被要求大改,雖然我本來就知道程式case常常這樣,可是工作還是很沒有成就感。

不過最近算是慢慢定下來,我也突然在各項功能的實作上寫得很順,突然就發現已經變成一個讓人挺有成就感的APP了。

雖然都是很簡單的功能拉,也算是順便幫腦中心的實驗打個廣告。



一開始的版權聲明,雖然我個人覺得意義不明,但就當是個感覺




首頁會顯示你本日完成度告示和累積受測費,右邊是問卷按鈕和設定按鈕
雖然目前只要不想填還是可以自己退出,不過還是做成完成才會出現離開按鈕

設定頁面

鬧鐘設定,會在你設定的時間跳出填寫提醒(還未美化...)

連線設定需要密碼

連線設定,連線的伺服器IP和所屬實驗帳號與專案,原則上管理員才會調整這些資料
Normal Mode取消勾選,APP問卷部分會改變,變成實驗者版的問卷

個人資訊設定



很無聊的問卷,關於版面的各個部分美國人要求的細緻入微




不想填其實可以跳過


上傳,成功上傳會更新受測費,沒有網路或失敗資料會存在手機裡,下次啟動自動重新上傳




說真的不是甚麼規模很大的APP,可是反反覆覆就被耗很多時間,期間還要同時弄伺服器和網頁。

感謝
蔡孟帥在伺服器的架設與管理上大力相助
古詩詩的版面設計


也算是個發文實驗,網誌文章的排版比我想像中的詭異一點
在圖片附近打字會一直被奇怪的東西綁架啊,在研究吧=口=


















冒險開始!!

B版雖然用的習慣,又很低調
但是果然想記錄開心的事,沒有圖片就還是覺得少了些甚麼

石頭也開twitch紀錄我們的冒險故事
我也想改用網誌紀錄些有趣的冒險、排球、美食還有一些創作成品和靈感等等

總之先吼一句話:

"GW2太棒拉~~~"