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);
}
}
最后就是一些细节上的修改了。