Unity3d Note4 (牧师与魔鬼改进版)

UML图

之前我曾做了一份牧师与魔鬼的小游戏,但在之前的基础上添加了一个动作管理器。
我将自己修改的主要部分做成UML图,如下:
这里写图片描述

  • ActionCallback接口是用来说明动作已完成。
  • ObjAction是所有动作的基类。ActionManager就是通过ObjAction这个接口来管理动作的。
  • MoveToAction是ObjAction的一个实现,它代表一个直线移动的动作。
  • SequenceAction也继承于ObjAction,它代表一系列的直线运动,即折线运动。
  • ActionManager是管理动作的类,负责执行、销毁动作。
  • FirstSceneActionManager是ActionManager的子类,FirstController就是通过它来管理所有动作的。在FirstSceneActionManager中对具体的需求做了封装,让代码更简洁。

    代码展示

    ActionCallBack

public interface ActionCallBack{
    void actionDone(ObjAction source);
}

ObjAction

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

    public GameObject gameObject;
    public Transform transform;
    public ActionCallBack actionCallBack;

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

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

MoveToAction

public class MoveToAction : ObjAction {
    public Vector3 target;
    public float speed;

    private MoveToAction() { }
    public static MoveToAction getAction(Vector3 target, float speed)
    {
        MoveToAction action = ScriptableObject.CreateInstance<MoveToAction>();
        action.target = target;
        action.speed = speed;
        return action;
    }

    public override void Start () { }

    public override void Update ()
    {
        this.transform.position = Vector3.MoveTowards(this.transform.position, target, speed * Time.deltaTime);
        if (this.transform.position == target)
        {
            this.destroy = true;
            this.actionCallBack.actionDone(this);
        }
    }
}

SequenceAction

public class SequenceAction : ObjAction, ActionCallBack {
    public List<ObjAction> objActions;
    public int repeat = 1;
    public int index = 0;

    public static SequenceAction getAction(List<ObjAction> objActions, int repeat, int index)
    {
        SequenceAction action = ScriptableObject.CreateInstance<SequenceAction>();
        action.objActions = objActions;
        action.repeat = repeat;
        action.index = index;
        return action;
    }

    public override void Update()
    {
        if (objActions.Count == 0)
            return;
        if (index < objActions.Count)
        {
            objActions[index].Update();
        }
    }

    public void actionDone(ObjAction source)
    {
        source.destroy = false;
        if(++index >= objActions.Count)
        {
            index = 0;
            if (repeat > 0)
                repeat--;
            if (repeat == 0)
            {
                destroy = true;
                actionCallBack.actionDone(this);
            }
        }
    }

    public override void Start()
    {
        foreach (ObjAction action in objActions)
        {
            action.gameObject = this.gameObject;
            action.transform = this.transform;
            action.actionCallBack = this;
            action.Start();
        }
    }

    private void OnDestroy()
    {
        foreach (ObjAction action in objActions)
            DestroyObject(action);
    }
}

ActionManager

public class ActionManager : MonoBehaviour, ActionCallBack {
    private Dictionary<int, ObjAction> actions = new Dictionary<int, ObjAction>();
    private List<ObjAction> waitingAdd = new List<ObjAction>();
    private List<int> waitingDelete = new List<int>();

    public void actionDone(ObjAction source)
    {

    }

    // Update is called once per frame
    void Update () {
        foreach (ObjAction action in waitingAdd)
            actions.Add(action.GetInstanceID(), action);
        waitingAdd.Clear();

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

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

    public void addAction(GameObject gameObject, ObjAction action, ActionCallBack actionCallBack)
    {
        action.gameObject = gameObject;
        action.transform = gameObject.transform;
        action.actionCallBack = actionCallBack;
        waitingAdd.Add(action);
        action.Start();
    }
}

FirstSceneActionManager

public class FirstSceneActionManager : ActionManager {
    public void moveBoat(BoatController boat)
    {
        MoveToAction action = MoveToAction.getAction(boat.getDestination(), boat.speed);
        this.addAction(boat.getGameobj(), action, this);
    }

    public void moveCharacter(MyCharacterController character, Vector3 dest)
    {
        Vector3 now = character.getPosition();
        Vector3 mid = now;
        if (dest.y > now.y)
            mid.y = dest.y;
        else
            mid.x = dest.x;
        ObjAction action1 = MoveToAction.getAction(mid, character.speed);
        ObjAction action2 = MoveToAction.getAction(dest, character.speed);
        ObjAction sequenceAction = SequenceAction.getAction(new List<ObjAction> { action1, action2 }, 1, 0);
        this.addAction(character.GetGameObject(), sequenceAction, this);
    }
}

最后就是一些细节上的修改了。

猜你喜欢

转载自blog.csdn.net/m0_37782473/article/details/79887184
今日推荐