3D遊戲編程與設計作業04

基本操作演練

  • 下載Fantasy Skybox FREE, 構建自己的遊戲場景
    由於個人主觀覺得Fantasy Skybox FREE不是特別好看,故而以下改用資源Wispy Skybox:在Asset Store中找到資源Wispy SkyboxDownloadImport。導入完成之後,直接將Wispy Skybox目錄下的Materials中的一個Skybox(自己選一個喜歡的)拖到場景中賦值
    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.csSSActionManger.cs
  • 預製:BoatBankPriest(添加組件Animator),Devil(添加組件Animator),如下圖所示:
    AssetPrefabs
    事實上,爲了讓代碼動態創建對象,我們需要將這些預製放在Resources目錄下。
    此外,爲了使BoatPriestDevil正常響應點擊事件,需要“外包”一個遊戲對象,例如對於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
  • 控制器
    • 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:動作管理基類
    管理SequenceActionSSAction,可以給它們傳遞遊戲對象,讓遊戲對象做動作或是一連串的動作,控制動作的切換。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倉庫:代碼傳送門

遊戲演示視頻

前往b站查看遊戲演示視頻

參考資料

前輩的博客
前輩的博客
前輩的博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章