基本演練操作
1.下載 Fantasy Skybox FREE, 構建自己的遊戲場景
- 建立天空盒
製作一個 6 面體材料 ,點擊菜單 Assets - create - Material,再點擊Inspector - shader - skybox - 6 sided ,按前後、上下、左右拖入 6 個圖片 - 製作完成,拖入項目 Material 目錄 。
- 構造草地樹木
點擊菜單 - Game object - 3d object - Terrain 建立地形。然後根據地形設計工具箱來種樹種草。
- 效果圖
簡單地建了一些山草樹木。
2.寫一個簡單的總結,總結遊戲對象的使用
- 遊戲對象的生成:遊戲對象可以通過代碼動態生成,也可以直接在Unity3D的界面中創建生成。
- 改變遊戲對象的狀態(動作、位移等):通過在代碼中調整相應的參數改變遊戲對象的狀態。
- 遊戲對象的部件:在Unity3D的界面中可以添加遊戲對象的部件,如聲音、效果、事件、UI、視頻等。
編程實踐
- 【牧師與魔鬼 動作分離版】
【新要求】:設計一個裁判類,當遊戲達到結束條件時,通知場景控制器遊戲結束
1.動作分類
根據上次作業的設計,把遊戲對象的主要動作分爲以下幾類:
動作 | 功能 |
---|---|
CCActionManager | 具體動作作爲類中的一個對象從而管理動作,同時繼承SSActionManager |
CCBoatMoving | 船移動的具體方法,繼承SSAction,將GenGameObject作爲其中一個對象 |
CCGetOffBoat | 牧師或魔鬼對象下船的具體方法,繼承SSAction,其中的對象有int型判斷河岸,與GameObject型對象接收具體作用的遊戲對象 |
CCGetOnTheBoat | 牧師或魔鬼對象上船的具體方法,繼承SSAction,其中的對象有GameObject型接收具體作用的遊戲對象 |
2.CCActionManager
CCActionManager是對具體遊戲事件的控制,其中包含三個方法:Start(),Update(),和SSActionEvent()。Start()方法中用於將SSDirector實例化,Update()方法中用於實現具體的遊戲事件,SSActionEvent()方法則是接口ISSActionCallback中的。
具體代碼如下:
public class CCActionManager : SSActionManager, ISSActionCallback
{
public GenGameObject sceneController;
public CCGetOnTheBoat getonA;
public CCGetOffBoat getoffB;
public CCBoatMoving boatmovingC;
// Use this for initialization
protected void Start()
{
sceneController = (GenGameObject)SSDirector.getInstance().currentScenceController;
sceneController.actionManager = this;
}
// Update is called once per frame
protected new void Update()
{
if (Input.GetMouseButtonDown(0) && sceneController.game == 0)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform.tag == "Devil" || hit.transform.tag == "Priest")
{
if (hit.collider.gameObject == sceneController.boat[0] || hit.collider.gameObject == sceneController.boat[1])
{
if (hit.collider.gameObject == sceneController.boat[0])
{
getoffB = CCGetOffBoat.GetSSAction(0);
this.RunAction(hit.collider.gameObject, getoffB, this);
}
else
{
getoffB = CCGetOffBoat.GetSSAction(1);
this.RunAction(hit.collider.gameObject, getoffB, this);
}
}
else
{
getonA = CCGetOnTheBoat.GetSSAction();
this.RunAction(hit.collider.gameObject, getonA, this);
}
}
else if (hit.transform.tag == "Boat" && sceneController.boatCapacity != 2)
{
print(hit.transform.tag);
boatmovingC = CCBoatMoving.GetSSAction();
this.RunAction(hit.collider.gameObject, boatmovingC, this);
}
}
}
base.Update();
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null)
{
//
}
}
3.船的動作
船的事件類有三個,分別是,CCBoatMoving、CCGetOffBoat和CCGetOnTheBoat。這三個具體的類全都繼承SSAction類,也同時在Start()函數中實例化了SSDirector。在Update中則是各自完成各自操作的。
【CCBoatMoving】
\\CCBoatMoving
public class CCBoatMoving : SSAction
{
public GenGameObject sceneController;
public static CCBoatMoving GetSSAction()
{
CCBoatMoving action = ScriptableObject.CreateInstance<CCBoatMoving>();
return action;
}
// Use this for initialization
public override void Start()
{
sceneController = (GenGameObject)SSDirector.getInstance().currentScenceController;
}
// Update is called once per frame
public override void Update()
{
if (sceneController.boat_position == 1)
{
sceneController.boat_position = 0;
while (this.transform.position != sceneController.boatStartPos)
this.transform.position = Vector3.MoveTowards(this.transform.position, sceneController.boatStartPos, 1);
}
else if (sceneController.boat_position == 0)
{
sceneController.boat_position = 1;
while (this.transform.position != sceneController.boatEndPos)
this.transform.position = Vector3.MoveTowards(this.transform.position, sceneController.boatEndPos, 1);
}
sceneController.check();
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
【CCGetOffBoat】
public class CCGetOffBoat : SSAction
{
public int side;
public GenGameObject sceneController;
public static CCGetOffBoat GetSSAction(int side)
{
CCGetOffBoat action = ScriptableObject.CreateInstance<CCGetOffBoat>();
action.side = side;
return action;
}
// Use this for initialization
public override void Start()
{
sceneController = (GenGameObject)SSDirector.getInstance().currentScenceController;
}
// Update is called once per frame
public override void Update()
{
if (sceneController.boat[side] != null)
{
sceneController.boat[side].transform.parent = null;
if (sceneController.boat_position == 1)
{
if (sceneController.boat[side].transform.tag == "Priest")
{
for (int i = 0; i < 3; i++)
{
if (sceneController.priests_end[i] == null)
{
sceneController.priests_end[i] = sceneController.boat[side];
sceneController.boatCapacity++;
break;
}
}
}
else if (sceneController.boat[side].transform.tag == "Devil")
{
for (int i = 0; i < 3; i++)
{
if (sceneController.devils_end[i] == null)
{
sceneController.devils_end[i] = sceneController.boat[side];
sceneController.boatCapacity++;
break;
}
}
}
}
else if (sceneController.boat_position == 0)
{
if (sceneController.boat[side].transform.tag == "Priest")
{
for (int i = 0; i < 3; i++)
{
if (sceneController.priests_start[i] == null)
{
sceneController.priests_start[i] = sceneController.boat[side];
sceneController.boatCapacity++;
break;
}
}
}
else if (sceneController.boat[side].transform.tag == "Devil")
{
for (int i = 0; i < 3; i++)
{
if (sceneController.devils_start[i] == null)
{
sceneController.devils_start[i] = sceneController.boat[side];
sceneController.boatCapacity++;
break;
}
}
}
}
sceneController.boat[side] = null;
}
sceneController.check();
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
【CCGetOnTheBoat】
public class CCGetOnTheBoat : SSAction
{
public GenGameObject sceneController;
public static CCGetOnTheBoat GetSSAction()
{
CCGetOnTheBoat action = ScriptableObject.CreateInstance<CCGetOnTheBoat>();
return action;
}
// Use this for initialization
public override void Start()
{
sceneController = (GenGameObject)SSDirector.getInstance().currentScenceController;
}
// Update is called once per frame
public override void Update()
{
if (sceneController.boatCapacity != 0)
{
if (sceneController.boat_position == 0)
{
for (int i = 0; i < 3; i++)
{
if (sceneController.devils_start[i] == gameobject)
{
sceneController.devils_start[i] = null;
sceneController.find = 1;
}
if (sceneController.priests_start[i] == gameobject)
{
sceneController.priests_start[i] = null;
sceneController.find = 1;
}
}
}
else if (sceneController.boat_position == 1)
{
for (int i = 0; i < 3; i++)
{
if (sceneController.devils_end[i] == gameobject)
{
sceneController.devils_end[i] = null;
sceneController.find = 1;
}
if (sceneController.priests_end[i] == gameobject)
{
sceneController.priests_end[i] = null;
sceneController.find = 1;
}
}
}
if (sceneController.find == 1)
gameobject.transform.parent = sceneController.boat_obj.transform;
if (sceneController.boat[0] == null && sceneController.find == 1)
{
sceneController.boat[0] = gameobject;
sceneController.boat[0].transform.tag = gameobject.transform.tag;
sceneController.boatCapacity--;
this.transform.localPosition = new Vector3(0, 1.2f, 0.19f);
}
else if (sceneController.boat[1] == null && sceneController.find == 1)
{
sceneController.boat[1] = gameobject;
sceneController.boat[1].transform.tag = gameobject.transform.tag;
sceneController.boatCapacity--;
this.transform.localPosition = new Vector3(0, 1.2f, -0.12f);
}
}
sceneController.find = 0;
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
4.裁判類
此次作業的新要求是要增加一個裁判類,判斷遊戲何時結束。其實就是將判斷遊戲結束的函數單獨出來變成一個類,代碼如下:
public class Judge : MonoBehaviour
{
CoastController fromCoast;
CoastController toCoast;
public BoatController boat;
public Judge(CoastController c1,CoastController c2, BoatController b)
{
fromCoast = c1;
toCoast = c2;
boat = b;
}
public int Check()
{ // 0->not finish, 1->lose, 2->win
int from_priest = 0;
int from_devil = 0;
int to_priest = 0;
int to_devil = 0;
int[] fromCount = fromCoast.GetobjectsNumber();
from_priest += fromCount[0];
from_devil += fromCount[1];
int[] toCount = toCoast.GetobjectsNumber();
to_priest += toCount[0];
to_devil += toCount[1];
if (to_priest + to_devil == 6) // win
return 2;
int[] boatCount = boat.GetobjectsNumber();
if (boat.get_State() == -1)
{ // boat at toCoast
to_priest += boatCount[0];
to_devil += boatCount[1];
}
else
{ // boat at fromCoast
from_priest += boatCount[0];
from_devil += boatCount[1];
}
if (from_priest < from_devil && from_priest > 0)
{ // lose
return 1;
}
if (to_priest < to_devil && to_priest > 0)
{
return 1;
}
return 0; // not finish
}
}
- 完整代碼和遊戲視頻見我的Github