魔鬼与牧师动作分离版


关于动作分离。可以通过对游戏对象增加可执行的动作,可以划分出很多的基础动作,如上船,下船,前进后退等。所以我们可以通过提取基础动作,然后使用类的方法来执行游戏对象的动作,同时通过配备动作管理者,让其去调度游戏对象执行动作。


动作管理者-SSActionManager
通过创教类来管理动作的集合,动作做完自动回收。并且展示了集合对象的使用方法。并且要执行start()方法。

publicclass SSActionManager : MonoBehaviour {

   
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction> ();
   
private List<SSAction> waitingAdd = new List<SSAction>();
   
private List<int> waitingDelete = new List<int>();
   
protectedvoidUpdate() {
       
foreach (SSAction ac in waitingAdd) {
            actions[ac.GetInstanceID()] = ac;
        }
        waitingAdd.Clear();
       
foreach (KeyValuePair<int, SSAction> kv in actions) {
            SSAction ac = kv.Value;
           
if (ac.destory) {
                waitingDelete.Add(ac.GetInstanceID());
            }
elseif (ac.enable) {
                ac.Update();
            }
        }
       
foreach(int key in waitingDelete) {
            SSAction ac = actions[key];
            actions.Remove(key);
            DestroyObject(ac);
        }
        waitingDelete.Clear();
    }

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

   
protectedvoidStart() {}
}

组合动作实现-CCSequeneceAction
SequenceAction继承了ISSActionCallback,因为组合动作是每一个动作的顺序完成,它管理这一连串动作中的每一个小的动作,所以当小的动作完成的时候,也要发消息告诉它,然后它得到消息后去处理下一个动作。SequenceAction也继承了SSAction,因为成个组合动作也需要游戏对象,也需要标识是否摧毁,也会有一个组合动作的管理者的接口,组成动作也是动作的子类,只不过是让具体的动作组合起来做罢了。
public class CCSequenceAction : SSAction, ISSActionCallback {

   
public List<SSAction> sequence;
   
public int repeat = - 1 ;
   
public int start = 0 ;


   
public static CCSequenceAction GetSSAction ( int repeat, int start, List<SSAction> sequence) {
        CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction> ();
        action.repeat = repeat;
        action.sequence = sequence;
        action.start = start;
       
return action;
    }

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

   
public void SSActionEvent (SSAction source, SSActionEventType events = SSActionEventType.Completed, int Param = 0 , string strParam = null , Object objectParam = null ) {
        source.destory =
false ;
       
this .start++;
       
if ( this .start >= sequence.Count) {
           
this .start = 0 ;
           
if (repeat > 0 ) repeat--;
           
if (repeat == 0 ) {
               
this .destory = true ;
               
this .callback.SSActionEvent( this );
            }
        }
    }
   
// Use this for initialization
   
public override void Start () {
       
foreach (SSAction action in sequence) {
            action.gameobject =
this .gameobject;
            action.transform =
this .transform;
            action.callback =
this ;
            action.Start();
        }
    }

   
void OnDestory() {}
}


牧师与魔鬼动作管理实现
CCMoveToAction(移动动作实现) 以speed的速度向target目的地移动
public class CCMoveToAction : SSAction {
   
public Vector3 target;
   
public float speed;

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

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

   
public override void Start () {}
}

SSActionManager(动作管理基类)
管理SequenceAction和SSAction,可以给它们传递游戏对象,让游戏对象做动作或是一连串的动作,控制动作的切换。SSActionManager继承了ISSActionCallback接口,通过这个接口,当动作做完或是连续的动作做完时候会告诉SSActionManager,然后SSActionManager去决定如何执行下一个动作。
public class SSActionManager : MonoBehaviour {

   
private Dictionary< int , SSAction> actions = new Dictionary< int , SSAction> ();
   
private List<SSAction> waitingAdd = new List<SSAction>();
   
private List< int > waitingDelete = new List< int >();
   
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.destory) {
                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();
    }

   
protected void Start () {}
}

SSAction (动作基类) 
SSAction是所有动作的基类。SSAction继承了ScriptableObject代表SSAction不需要绑定GameObject对象,且受Unity引擎场景管理

public class SSAction : ScriptableObject {

   
public bool enable = true ;
   
public bool destory = 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 ();
    }
}

SSDirector 
最后SSDirector接收到游戏对象需要移动的时候,只要传给MySceneActionManager相应的参数和游戏对象就可以进行移动啦 
public enum State { WIN, LOSE, PAUSE, CONTINUE , START };
public class SSDirector : System.Object {

    private static SSDirector _instance;
    public int totalSeconds = 60;
    public int leaveSeconds;
    public bool onCountDown = false;
    public string countDownTitle = "Start";

    public ISceneController currentSceneController { get; set; }
    public State state { get; set; }
    public bool running { get; set; }

    // get instance anytime anywhere!
    public static SSDirector getInstance() {
        if (_instance == null) {
            _instance = new SSDirector ();
        }
        return _instance;
    }

    public int getFPS() {
        return Application.targetFrameRate;
    }

    public void setFPS(int fps) {
        Application.targetFrameRate = fps;
    }

    public IEnumerator DoCountDown() {
        while (leaveSeconds > 0) {
            yield return new WaitForSeconds (1f);
            leaveSeconds--;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

FirstController.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FirstController : MonoBehaviour, IUserAction, ISceneController {

    public CCActionManager actionManager;

    List<GameObject> LeftObjList = new List<GameObject>();
    List<GameObject> RightObjList = new List<GameObject>();
    GameObject[] boat = new GameObject[2];

    GameObject boat_obj, leftShore_obj, rightShore_obj;

    Vector3 LeftShorePos = new Vector3(-12, 0, 0);
    Vector3 RightShorePos = new Vector3(12, 0, 0);
    Vector3 BoatLeftPos = new Vector3(-4, 0, 0);
    Vector3 BoatRightPos = new Vector3(4, 0, 0);

    void Awake() {
        SSDirector director = SSDirector.getInstance();
        director.setFPS(60);
        director.currentSceneController = this;
        director.currentSceneController.LoadResources();
        director.leaveSeconds = director.totalSeconds;
    }

    void Start () {
        SSDirector.getInstance().state = State.PAUSE;
        SSDirector.getInstance().countDownTitle = "Start";
        actionManager = GetComponent<CCActionManager>() as CCActionManager;
    }

    void Update() {
        check();
    }

    public void LoadResources() {
        GameObject priest_obj, devil_obj;
        Camera.main.transform.position = new Vector3(0, 0, -20);

        leftShore_obj = Instantiate(Resources.Load("prefabs/Shore"), LeftShorePos, Quaternion.identity) as GameObject;
        rightShore_obj = Instantiate(Resources.Load("prefabs/Shore"), RightShorePos, Quaternion.identity) as GameObject;
        leftShore_obj.name = "left_shore";
        rightShore_obj.name = "right_shore";

        boat_obj = Instantiate(Resources.Load("prefabs/Boat"), BoatLeftPos, Quaternion.identity) as GameObject;
        boat_obj.name = "boat";
        boat_obj.transform.parent = leftShore_obj.transform;

        for (int i = 0; i < 3; ++i) {
            priest_obj = Instantiate(Resources.Load("prefabs/Priest")) as GameObject;
            priest_obj.name = i.ToString();
            priest_obj.transform.position = new Vector3(-16f + 1.5f * Convert.ToInt32(priest_obj.name), 2.7f, 0);
            priest_obj.transform.parent = leftShore_obj.transform;
            LeftObjList.Add(priest_obj);

            devil_obj = Instantiate(Resources.Load("prefabs/Devil")) as GameObject;
            devil_obj.name = (i + 3).ToString();
            devil_obj.transform.position = new Vector3(-16f + 1.5f * Convert.ToInt32(devil_obj.name), 2.7f, 0);
            devil_obj.transform.parent = leftShore_obj.transform;
            LeftObjList.Add(devil_obj);
        }
    }

    public void click() {
        GameObject gameObj = null;

        if (Input.GetMouseButtonDown(0) && 
            (SSDirector.getInstance().state == State.START || SSDirector.getInstance().state == State.CONTINUE)) {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit)) gameObj = hit.transform.gameObject;
        }

        if (gameObj == null) return;
        else if (gameObj.name == "0" || gameObj.name == "1" || gameObj.name == "2"
            || gameObj.name == "3" || gameObj.name == "4" || gameObj.name == "5")
            MovePeople(gameObj);
        else if(gameObj.name == "boat") MoveBoat();
    }

    void MovePeople(GameObject people) {
        int shoreNum, seatNum;

        if (people.transform.parent == boat_obj.transform.parent && (boat[0] == null || boat[1] == null)) {
            seatNum = boat[0] == null ? 0 : 1;
            if (people.transform.parent == leftShore_obj.transform) {
                shoreNum = 0;
                for (int i = 0; i < LeftObjList.Count; i++) {
                    if (people.name == LeftObjList[i].name) {
                        Debug.Log (actionManager);
                        actionManager.getOnBoat(people, shoreNum, seatNum);
                        LeftObjList.Remove(LeftObjList[i]);
                    }
                }
            } else {
                shoreNum = 1;
                for (int i = 0; i < RightObjList.Count; i++) {
                    if (people.name == RightObjList[i].name) {
                        actionManager.getOnBoat(people, shoreNum, seatNum);
                        RightObjList.Remove(RightObjList[i]);
                    }
                }
            }
            boat[seatNum] = people;
            people.transform.parent = boat_obj.transform;
        } else if (people.transform.parent == boat_obj.transform) {
            shoreNum = boat_obj.transform.parent == leftShore_obj.transform ? 0 : 1;
            seatNum = (boat[0] != null && boat[0].name == people.name) ? 0 : 1;

            actionManager.getOffBoat(people, shoreNum);

            boat[seatNum] = null;
            if(shoreNum == 0) {
                people.transform.parent = leftShore_obj.transform;
                LeftObjList.Add(people);
            } else {
                people.transform.parent = rightShore_obj.transform;
                RightObjList.Add(people);
            }
        }
    }

    void MoveBoat() {
        if (!(boat[0]==null && boat[1] == null)) {
            actionManager.moveBoat(boat_obj);
            boat_obj.transform.parent = boat_obj.transform.parent == leftShore_obj.transform ? rightShore_obj.transform : leftShore_obj.transform;
        }
    }

    public void check() {
        int left_d = 0, left_p = 0, right_d = 0, right_p = 0;

        foreach (GameObject element in LeftObjList) {
            if (element.tag == "Priest") left_p++;
            if (element.tag == "Devil") left_d++;
        }

        foreach (GameObject element in RightObjList) {
            if (element.tag == "Priest") right_p++;
            if (element.tag == "Devil") right_d++;
        }

        for (int i = 0; i < 2; i++) {
            if (boat[i] != null && boat_obj.transform.parent == leftShore_obj.transform) {
                if (boat[i].tag == "Priest") left_p++;
                else left_d++;
            }
            if (boat[i] != null && boat_obj.transform.parent == rightShore_obj.transform) {
                if (boat[i].tag == "Priest") right_p++;
                else right_d++;
            }
        }

        if ((left_d > left_p && left_p != 0) || (right_d > right_p && right_p != 0) || SSDirector.getInstance().leaveSeconds == 0)
            SSDirector.getInstance().state = State.LOSE;
        else if (right_d == right_p && right_d == 3) SSDirector.getInstance().state = State.WIN;
    }

    public void Pause() {
        SSDirector.getInstance().state = State.PAUSE;
    }

    public void Resume() {
        SSDirector.getInstance().state = State.CONTINUE;
    }

    public void Restart() {
        Application.LoadLevel(Application.loadedLevelName);
        SSDirector.getInstance().state = State.START;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值