github传送门:https://github.com/dongzizhu/unity3DLearning
Fantasy Skybox FREE的使用
首先我们在Asset Store下载好Fantasy Skybox Free,然后import。
接着只需要在materials文件夹中创建一个新的material,然后将其shader选择成Skybox/6 sided,然后对六个方向分别选择对应位置的图片即可。
接下来直接点击运行既可以看到我们天空盒的效果。
总结游戏对象的使用
游戏对象是面向对象变成思想的一种发展,在Unity3D里,每一个游戏中用到的单位都可以是一个游戏对象,然后通过统一的方式来管理。游戏对象可以是unity自带的正方体、球体等三维物体,甚至camera也可以是游戏对象;每个游戏对象都有属性和组件,其中最重要的属性就是transform,用来管理其位置,然后组件可以是脚本,来实现该游戏对象的行为逻辑,也可以是纹理材质等,来完善游戏的画面。通过这样的方式,游戏的运行被强行解耦合,是代码逻辑更加清晰,也是所有的对象和行为更加便于管理。
牧师与魔鬼动作分离版
设计一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束。
我们直接在上次的代码上进行改进。增加一个动作管理器来管理船和人物的移动,然后增加一个Referee类,来判别是否结束当前游戏。在之前的MVC模型中,我们直接由一个Movable类来管理移动的代码,然后在两种对象中写出了相应的方法;这次要实现所谓动作分离,就是指将管理动作的部分从这些controller中分离,单独抽象出来,其实就是将movable进一步抽象,变成一个MoveController的感觉。所以原本是有controller直接调用model的方法来管理action,现在转为调用ActionManager中的相应代码。
Referee也是类似的感觉,直接将原本的check()分离出来形成一个referee类即可。
ActionController的核心部分是继承了SSActionManager的ActionManager类。
public class ActionManager : SSActionManager
{
public void MoveBoat(BoatController boatCtrl) {
SSMoveToAction action;
Vector3 from = new Vector3(5, 1, 0);
Vector3 to = new Vector3(-5, 1, 0);
float speed = 50;
if (boatCtrl.get_to_or_from() == -1)
action = SSMoveToAction.GetSSMoveToAction(from, speed);
else action = SSMoveToAction.GetSSMoveToAction(to, speed);
boatCtrl.set_to_or_from();
AddAction(boatCtrl.getGameobj(), action, this);
}
public void MoveCharacter(MyCharacterController itemCtrl, Vector3 finalDes) {
float time = 3;
float g = -3;
Vector3 v0;
float vy_ByGravity = 0;
float stepTime = 0.1f;
Vector3 currentDes = itemCtrl.getPosition();
List<SSAction> divide = new List<SSAction>();
// the des here is the final destination
v0 = new Vector3((finalDes.x - itemCtrl.getPosition().x) / time,
(finalDes.y - itemCtrl.getPosition().y) / time - 0.5f * g * time, (finalDes.z - itemCtrl.getPosition().z) / time);
// divide the curve to many parts
for (int i = 0; i < time / stepTime - 1; i++) {
// change the vy
vy_ByGravity += g * stepTime;
// set current des
currentDes += v0 * stepTime;
currentDes.y += vy_ByGravity * stepTime;
// get the current speed
float currentSpeed = Mathf.Sqrt(v0.x * v0.x + (v0.y + vy_ByGravity) * (v0.y + vy_ByGravity));
// add one of the movements
SSAction temp = SSMoveToAction.GetSSMoveToAction(currentDes, currentSpeed * 10);
divide.Add(temp);
}
SSAction seqAction = SequenceAction.GetSequenceAction(1, 0, divide);
AddAction(itemCtrl.getGameobj(), seqAction, this);
}
}
其余的部分大多照抄ppt上的代码就行,这里就不一一贴出了,具体请见github项目。然后就是Referee类,我们让其也在boat上进行实例化。
public class Referee {
private BoatController boat;
public Referee(BoatController b){
boat = b;
}
public int Check(CoastController fromCoast, CoastController toCoast, BoatController boat)
{
int from_priest = 0;
int from_devil = 0;
int to_priest = 0;
int to_devil = 0;
int[] fromCount = fromCoast.getCharacterNum ();
from_priest += fromCount[0];
from_devil += fromCount[1];
int[] toCount = toCoast.getCharacterNum ();
to_priest += toCount[0];
to_devil += toCount[1];
if (to_priest + to_devil == 6) // win
return 2;
int[] boatCount = boat.getCharacterNum ();
if (boat.get_to_or_from () == -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
}
}
这里我还添加了天空盒,最终的实现效果如图所示。因为游戏过程和之前的版本一样,只是代码的架构稍有变化,所以这里就不再上传一个视频了。