基本演练操作
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