基本操作演練
- 下載
Fantasy Skybox FREE
, 構建自己的遊戲場景
由於個人主觀覺得Fantasy Skybox FREE
不是特別好看,故而以下改用資源Wispy Skybox
:在Asset Store中找到資源Wispy Skybox
,Download
,Import
。導入完成之後,直接將Wispy Skybox
目錄下的Materials
中的一個Skybox(自己選一個喜歡的)拖到場景中賦值
- 寫一個簡單的總結,總結遊戲對象的使用
Unity中的所有實體都屬於遊戲對象(GameObject),其主要操作有如下幾種:-
創建遊戲對象
- 方法一:菜單->GameObject->{3D Object(Cube, Sphere, Capsule, ……),Camera攝像機,Light光源,……}
- 方法二:使用GameObject.CreatPrimitive()函數來創建Unity自帶的模型
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
- 方法三:使用Instantiate()函數進行遊戲物體的實例化
boat = Object.Instantiate(Resources.Load("Boat", typeof(GameObject)), boat_position, Quaternion.identity) as GameObject;
-
獲取遊戲對象
- 方法一:在代碼裏聲明public類型GameObject,在Inspector屬性欄中指定遊戲對象(往往是直接將預製Prefab拖過去賦值)
- 方法二:通過對象名稱獲取對象,例如
obj = GameObject.Find("Sphere");
-
爲遊戲對象添加組件和修改組件
新創建的遊戲對象本身僅僅具有很少的一部分屬性,爲了讓它具備一些其他的功能,就必須給它添加遊戲組件;
添加遊戲組件的時候,需要使用AddComponent()方法,而刪除某一個組件的時候需要使用Object.Destory()的方法;
需要刪除的遊戲對象或組件,如果刪除的是一個對象,則該對象的所有組件將一併被刪除;例如,
move = boat.AddComponent(typeof(Move)) as Move; click = boat.AddComponent(typeof(Click)) as Click;
-
克隆遊戲對象
- 首先,在場景中創建被克隆對象
- 在主攝像機上掛在複製腳本——使用
Instantiate()
方法實例化遊戲對象 - 在腳本的Inspector中指定被克隆對象(腳本中將其設爲public)
-
編程實踐-牧師與魔鬼小遊戲進階版(動作分離版)
程序要求
-
使用 C# 集合類型 有效組織對象
-
整個遊戲僅主攝像機和一個Empty對象,其他對象必須代碼動態生成!!! 。 整個遊戲不許出現Find遊戲對象,SendMessage這類突破程序結構的通訊耦合語句。違背本條準則,不給分
-
請使用課件架構圖編程,不接受非
MVC
結構程序 -
注意細節,例如:船未靠岸,牧師與魔鬼上下船運動中,均不能接受用戶事件!
-
2019新要求:設計一個裁判類,當遊戲達到結束條件時,通知場景控制器遊戲結束
-
代碼改進:
- 設計裁判類(提取出Check方法)
-
動作分離:
- 把每個需要移動的遊戲對象的移動方法提取出來,建立一個動作管理器來管理不同的移動方法。
- 對於上一個版本,每一個可移動的遊戲對象的組件都有一個Move腳本,當遊戲對象需要移動時候,遊戲對象自己調用Move腳本中的方法讓自己移動。而動作分離版,則剝奪了遊戲對象自己調用動作的能力,建立一個動作管理器,通過場景控制器(在我的代碼設計中是Controller)把需要移動的遊戲對象傳遞給動作管理器,讓動作管理器去移動遊戲對象。
- 當動作很多或是需要做同樣動作的遊戲對象很多的時候,使用動作管理器可以讓動作很容易管理,也提高了代碼複用性。
遊戲場景製作
資源下載:
- Devil animated character【惡魔】
- Toony Tiny RTS Demo【牧師】
- Lowpoly Paper Boat【船】
- Rounded Blocks【河岸】
- Wispy Skybox【天空(背景)】
場景佈置:
- Skybox:參見前面所述
- 靜態遊戲對象:主攝像機和空對象MAIN(掛載腳本
Click.cs
,UseGUI.cs
,Controller.cs
和SSActionManger.cs
) - 預製:
Boat
,Bank
,Priest
(添加組件Animator
),Devil
(添加組件Animator
),如下圖所示:
事實上,爲了讓代碼動態創建對象,我們需要將這些預製放在Resources
目錄下。
此外,爲了使Boat
,Priest
,Devil
正常響應點擊事件,需要“外包”一個遊戲對象,例如對於Priest
,用一個Capsule
作爲其父親,將資源商店中下載的預製作爲Capsule
的子對象;並且爲了達到較好的顯示效果,設置一定的位置偏移和大小比例,這裏我採用的是:
對於Priest:
GameObject | Position | Scale |
---|---|---|
Capsule | (0,0,0) | (3,3,3) |
從資源商店中下載的預製對象(TT_RTS_Demo_Character) | (0,-1.2,0) | (2,2,2) |
對於Devil:
GameObject | Position | Scale |
---|---|---|
Capsule | (0,0,0) | (1.5,3,1.5) |
從資源商店中下載的預製對象(devil@idle) | (0.2,-1.4,0) | (5,2.5,5) |
對於Boat:
GameObject | Position | Scale |
---|---|---|
Cylinder | (0,0,0) | (15,1,8) |
從資源商店中下載的預製對象(black_perl) | (0,-1,0) | (0.001,0.01,0.002) |
- 遊戲預製對象座標和大小設置
GameObject | Position | Rotation | Scale |
---|---|---|---|
Main Camera | (0,1,0) | (0,0,0) | (1,1,1) |
MAIN | (0,0,0) | (0,0,0) | (1,1,1) |
Boat | (-10,0,40) | (0,10,0) | (0.01,0.01,0.01) |
BoatSeat1 | (-6,1,40) | / | / |
BoatSeat2 | (-14,1,40) | / | / |
Bank | (-45,0,70) | (0,0,0) | (40,5,60) |
Priest | / | (0,90,0) | (3,3,3) |
Devil | / | (0,90,0) | (1.5,3,1.5) |
PBankPosition1 | (-28,3,70) | / | / |
PBankPosition2 | (-37,3,70) | / | / |
PBankPosition3 | (-46,3,70) | / | / |
DBankPosition1 | (-30,3,40) | / | / |
DBankPosition2 | (-26,3,40) | / | / |
DBankPosition3 | (-22,3,40) | / | / |
動態生成代碼時,另一側的座標只要做x座標的對稱運算即可
遊戲場景預製結果:
代碼設計
MVC架構——界面人機交互程序設計的一種架構模式
將程序分爲三部分:
- 模型
- MVC架構模型
SSDirector.cs
ISceneController.cs
IUserAction.cs
SSAction.cs
SSMoveToAction.cs
SequenceAction.cs
ISSActionCallback.cs
SSActionManager.cs
MySceneActionManger.cs
Click.cs
Judge.cs
- 遊戲對象模型
RoleModel.cs
BoatModel.cs
BankModel.cs
PlayAnimation.cs
- MVC架構模型
- 控制器
Controller.cs
- 界面
UserGUI.cs
與上一版本的比較:
- 去除了
Move.cs
腳本 - 用戶動作列表中去除了
Check()
,而把這一動作交給Judge
實現 - 增加了
Judge.cs
腳本和相應的動作管理的腳本
模型
模型主要是描述數據對象及關係
RoleModel.cs
:牧師/魔鬼角色模型BoatModel.cs
:船模型(記錄了船的位置、船上的空位位置)BankModel.cs
:河岸模型(記錄了河岸位置、河岸上的空位位置)ISceneController
:場記(接口)
其職責大致如下:- 管理本次場景所有的遊戲對象
- 協調遊戲對象(預製件級別)之間的通訊
- 響應外部輸入事件
- 管理本場次的規則(裁判)
- 各種雜務
這裏,我們用一個LoadResources()
方法實現這些職責:
public interface ISceneController //場記接口 { void LoadResources(); }
IUserAction
:用戶動作“列表”(接口)- 移動船
- 移動角色
- 重新開始
public interface IUserAction //用戶動作“列表”接口 { void MoveBoat();//移動船 void MoveRole(RoleModel role);//移動角色 void Restart();//重新開始 }
SSDirector
:導演(單實例模式)
創建SSDirector
類,其職責大致如下:
- 獲取當前遊戲的場景
- 控制場景運行、切換、入棧與出棧
- 暫停、恢復、退出
- 管理遊戲全局狀態
- 設定遊戲的配置
- 設定遊戲全局視圖SSAction
:動作基類
SSAction
是所有動作的基類。它集成了ScriptableObjects
,代表SSAction
不需要綁定GameObject
對象,且受Unity引擎場景管理SSMoveToAction.cs
:移動動作實現(以speed的速度向target目的地移動)SequenceAction.cs
:組合動作實現
SequenceAction
繼承了ISSActionCallback
,因爲組合動作是每一個動作的順序完成,它管理這一連串動作中的每一個小的動作,所以當小的動作完成的時候,也要發消息告訴它,然後它得到消息後去處理下一個動作。SequenceAction
也繼承了SSAction
,因爲成個組合動作也需要遊戲對象,也需要標識是否摧毀,也會有一個組合動作的管理者的接口,組成動作也是動作的子類,只不過是讓具體的動作組合起來做罷了。ISSActionCallback.cs
:動作事件接口
作爲動作和動作管理者的接口(組合動作也可以是動作管理者),動作管理者繼承這個接口,並且實現接口的方法。當動作完成時,動作會調用這個接口,發送消息通知動作管理者對象動作已完成,然後管理者會對下一個動作進行處理。SSActionManager.cs
:動作管理基類
管理SequenceAction
和SSAction
,可以給它們傳遞遊戲對象,讓遊戲對象做動作或是一連串的動作,控制動作的切換。SActionManager
繼承了ISSActionCallback
接口,通過這個接口,當動作做完或是連續的動作做完時候會告訴SSActionManager
,然後SSActionManager
去決定如何執行下一個動作。Click.cs
:點擊事件腳本(掛載在MAIN對象上即可)MySceneActionManger.cs
:移動動作管理實現
船的移動是一個SSMoveToAction
動作就可以實現,而角色的移動需要兩個SSMoveToAction
動作組合(先垂直後水平移動或先水平後垂直移動)。然後設置當前場景控制器的動作管理者爲MySceneActionManger
,這樣場景控制器就可以調用動作管理器的方法實現不同遊戲對象的移動了。Judge.cs
:裁判類,當遊戲達到結束條件時,通知場景控制器遊戲結束
設置當前場景控制器的裁判爲Judge
(傳入當前場景控制器的boat
構建Judge
),將IUserAction
中的Check()
方法遷移至本類中,其中的start_land
上的牧師與魔鬼個數,end_land
上的牧師與魔鬼個數由場景控制器調用本類的Check()
方法時傳入即可。
控制器
Controller.cs
:接受用戶事件,控制上述各模型的變化(掛載在MAIN
對象下)
用戶界面
UserGUI
:顯示模型,將人機交互事件交給控制器處理- 處理鼠標點擊事件(交給控制器
Controller
) - 渲染GUI(
OnGUI()
),接收事件
- 處理鼠標點擊事件(交給控制器
詳細代碼參考我的github倉庫:代碼傳送門