[Unity3D课堂作业] 改进版:Priests and Devils 牧师与恶魔

还是先po一下效果咯~~



这次作业其实就是:将上次作业在Update()函数一帧帧改位置控制运动,改为类似cocos2d的一个Action方法控制物体自己运动,也就是所谓的面向对象的设计。但其实本质上还是在每一帧的时间里做改动。


课件上面那个设计框架基本上可以plug and play 即插即用,所以就直接套过来用了,只需要在CCActionManager处与上次作业的mainSceneController交互即可


(课件截图)


因此修改后的项目UML类图如下(CCActionManager那里即与上图连接


由于在上次作业我都是在控制船运动的BoatBehaviour和控制人物运动的PersonStatus里修改位置,所以这次也只需要主要在这两个脚本里修改即可,很方便。


下面说一下与之前作业修改的地方:

1、添加interface接口IAddAction,有两个方法:增加单独动作和组合动作

public interface IAddAction {
    void addSingleMoving(GameObject sourceObj, Vector3 target, float speed);
    void addCombinedMoving(GameObject sourceObj, Vector3[] target, float[] speed);
}

2、在mainSceneController里实现IAddAction接口方法。但在这之前先把CCActionManager声明为其一个私有成员,并在CCActionManager里真正实现addSingleMoving()、addCombinedMoving()两个方法:

public void addSingleMoving(GameObject sourceObj, Vector3 target, float speed) {
    this.runAction(sourceObj, CCMoveToAction.CreateSSAction(target, speed), this);
}

public void addCombinedMoving(GameObject sourceObj, Vector3[] target, float[] speed) {
    List<SSAction> acList = new List<SSAction>();
    for (int i = 0; i < target.Length; i++) {
        acList.Add(CCMoveToAction.CreateSSAction(target[i], speed[i]));
    }
    CCSequeneActions MoveSeq = CCSequeneActions.CreateSSAction(acList);
    this.runAction(sourceObj, MoveSeq, this);
}
    而 mainSceneController里实现 IAddAction接口方法仅仅是通过CCActionManager私有成员调用自身的两个方法即可。

3、明显动作结束后会回调CCActionManager里面的SSActionEvent方法。所以需要在此回调函数里面告知mainSceneController动作(船/人)已经完成:

public void SSActionEvent(SSAction source, SSActionEventType eventType = SSActionEventType.Completed, int intParam = 0, string strParam = null, object objParam = null) {
    if (source.gameObject.name.Equals("Boat")) {   //船完成动作
        scene.boatReachBank();
    }
    else {   //人完成动作
        scene.personFinishMoving();
    }
}

4、添加动作的基本框架大概就做好了,只需要在控制船和人的脚本里调用即可

5、BoatBehaviour脚本

    (1)之前是在此脚本的Update()方法里一帧帧的改位置,这次去掉

    (2)之前是通过GenGameObjects调用BoatBehaviour的setBoatMove方法触发船移动。因此只需修改setBoatMove方法,把原来 直接更改位置变成:

addAction.addSingleMoving(this.gameObject, LOCATION_SET.boat_right_LOC, BOAT_SPEED);

6、PersonStatus脚本:

    在这里由于人要上下船,所以移动会有两次,如先向上再向右。此时只需找到中间转折点的位置,将两个动作作为序列动作即可。以下为分解动作并添加的方法:

void divideThePosAndSetMove(Vector3 target, bool isGetOn) {
    Vector3[] dividedPos = new Vector3[2];
    float[] speedSet = new float[2];

    if (isGetOn) {
        dividedPos[0] = new Vector3(target.x, this.transform.position.y, 0);
        dividedPos[1] = target;
    }
    else {
        dividedPos[0] = new Vector3(this.transform.position.x, target.y, 0);
        dividedPos[1] = target;
    }

    speedSet[0] = PERSON_SPEED;
    speedSet[1] = PERSON_SPEED;

    addAction.addCombinedMoving(this.gameObject, dividedPos, speedSet);
    gameStatus.setObjMoving(MOVEMENT.Moving);
}


7、好了。分离动作的步骤应该就做完了。还有就是要设置船移动和人移动不能人机交互。


8、在上一次作业我已经在船的脚本里面设置了一个isMoving的私有变量来判断了。但是这次还有人的移动,在船/人两个脚本里面都设置这样的私有变量就有点累赘了,所以直接在场景控制脚本mainSceneController里设置一个公用的isGameObjectMoving私有变量。同时设置修改的public方法setObjMoving()。在船移动和人移动的开始时候调用此方法,说明正在有gameObjet移动,而此时其他的动作在启动前都会根据IQueryGameStatus 查询当前是否有其他物体在运动,如有即自身动作无效。

public void setObjMoving(bool isMoving) {
    isGameObjectMoving = isMoving;
}


9、上面第3点也已经提到了,CCActionManager里面有个回调方法SSActionEvent,即每当有动作结束的时候会调用。所以只需要在这里调用mainSceneController的方法,修改isGameObjectMoving的值即可。之后又可以允许动作产生了。

public void boatReachBank() {
    myGenGameObjects.boatReachBank();
    isGameObjectMoving = MOVEMENT.NotMoving;
}

public void personFinishMoving() {
    Debug.Log("person finish moving");
    isGameObjectMoving = MOVEMENT.NotMoving;
}


10、这样就差不多了~这次作业比较简单就不放代码啦害羞





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值