unity3d 牧师与恶魔动作分离

贴一个github地址
https://github.com/ddghost/unity3d/tree/master/unity%20hw3

实现牧师与魔鬼的动作分离

按照老师给的层次进行改进
unity3d 牧师与恶魔动作分离_第1张图片

刚开始对动作的分离还不是太清晰,现在想想,动作分离应该就是把游戏里的动作实现从场记那里抽离出来,另外写一个动作管理器来提供接口进行对象动作的增删。
最开始的动作实现(仅以船为例,由于牧师与魔鬼是直接到船上的,所以没有位移)是通过在船上挂载一个处理鼠标点击的脚本(toSolveClick)和一个运动脚本(updateBoatMove)。

public boatController(string size){
        boat = Object.Instantiate (Resources.Load ("prefabs/boat", typeof(GameObject))
            , rightPos , Quaternion.identity, null) as GameObject ;
        boat.name = "boat";
        //给船对象添加两个脚本
        toSolveClick = boat.AddComponent (typeof(firstScenceSolveClick)) as firstScenceSolveClick;
        toSolveClick.setName (boat.name);
        updateBoatMove = boat.AddComponent (typeof(boatMoveBeahave)) as boatMoveBeahave;
        //
        defaultSize = size;
        this.size = defaultSize;
    }

当鼠标点击后,脚本通知场记,然后场记进行处理。

firstScenceUserAction action ;
void OnMouseDown(){
        if (action.getStatus() != "playing") {
            return;
        }
        else{
            if (characterName == "boat") {
                action.boatMove ();
            }
            else {
                action.getBoatOrGetShore (name);
            }
        }
    }

若符合开船条件就修改运动脚本中的目的地来实现运动。

    public void boatMove(){
        //判断船是否能开
        if (!myBoat.ifEmpty () && myBoat.getRunningState() != "running") {
            string toSize;
            string[] passengers = myBoat.getPassengerName();
            if (myBoat.size == "left") {
                toSize = "right";
            }
            else {
                toSize = "left";
            }
            // 船到另一岸了,因此船上的人物也要到另一岸,
            for (int loop = 0; loop < 2; loop++) {
                for (int loop1 = 0; loop1 < numOfPirestOrDevil * 2; loop1++) {
                    if (peopleCtrl [loop1].getName () == passengers [loop]) {
                        peopleCtrl [loop1].size = toSize;
                    }
                }
            }
            //开船
            myBoat.move ( );
        }

    //myboat里的move函数,两端代码在不同的类中
    public void move(){
        if (size == "right") {
            updateBoatMove.setAim (leftPos);
            size = "left";
        } 
        else {
            updateBoatMove.setAim (rightPos);
            size = "right";
        }
    }

这样的话,运动的代码是在场记中实现的,场记做的东西就有点太多了。

现在有了动作管理器,可以通过动作管理器给对象添加动作删除动作,而不是像之前那样一直挂着一个脚本,这样看起来也就更科学了。
逻辑依旧是点击船后,船上的脚本通知场记,场记判断是否能开船后通知船的控制器。
代码与之前不同的是不用再添加两个脚本到船上。

public boatController(string size){
        boat = Object.Instantiate (Resources.Load ("prefabs/boat", typeof(GameObject))
            , rightPos , Quaternion.identity, null) as GameObject ;
        boat.name = "boat";
        //只有一个脚本了
        toSolveClick = boat.AddComponent (typeof(firstScenceSolveClick)) as firstScenceSolveClick;
        //
        toSolveClick.setName (boat.name);
        defaultSize = size;
        this.size = defaultSize;
    }

还修改了船的控制器中的move函数。

public void move(CCActionManager actionManager){
        CCBoatMoveing boatMove = CCBoatMoveing.GetSSAction (10f);
        if (size == "right") {
            boatMove.aim = leftPos;
            size = "left";
        } 
        else {
            boatMove.aim = rightPos;
            size = "right";
        }
        //交由动作管理器添加动作
        actionManager.RunAction (boat , boatMove , null );
    }

动作和动作管理器的基类都是照搬老师代码,虽然这次的动作只有船的左右移动,并且也没有进行动作回调(ISSActionCallback),但是也还是能帮助加深对动作管理器的理解。

//动作基类
public enum SSActionEventType : int { Started, Competeted }

public interface ISSActionCallback
{
    void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
        int intParam = 0, string strParam = null, Object objectParam = null);
}

public class SSAction : ScriptableObject
{
    public bool enable = true;
    public bool destroy = false;

    public GameObject gameobject { get; set; }
    public Transform transform { get; set; }
    public ISSActionCallback callback { get; set; }

    protected SSAction() { }

    public virtual void Start()
    {
        throw new System.NotImplementedException();
    }

    public virtual void Update()
    {
        throw new System.NotImplementedException();
    }
}

//动作管理器基类
public class SSActionManager : MonoBehaviour {
    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
    private List waitingAdd = new List();
    private List<int> waitingDelete = new List<int>();

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    protected void Update()
    {
        foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
        waitingAdd.Clear();

        foreach (KeyValuePair<int, SSAction> kv in actions)
        {
            SSAction ac = kv.Value;
            if (ac.destroy)
            {
                waitingDelete.Add(ac.GetInstanceID());
            }
            else if (ac.enable)
            {
                ac.Update();
            }
        }

        foreach (int key in waitingDelete)
        {
            SSAction ac = actions[key]; actions.Remove(key); DestroyObject(ac);
        }
        waitingDelete.Clear();
    }

    public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager)
    {
        action.gameobject = gameobject;
        action.transform = gameobject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }
}

你可能感兴趣的:(unity3d)