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?

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

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