這次的作業是跟着這位師兄:@MokHoYin來做的,加上了自己的一些理解,師兄博客地址:http://blog.csdn.net/qq_33000225/article/details/70045292
我就直接貼代碼了,不過有點長-_-
1.GameEventManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Patrols;
public class GameEventManager : MonoBehaviour {
public delegate void GameScoreAction();
public static event GameScoreAction myGameScoreAction;
public delegate void GameOverAction();
public static event GameOverAction myGameOverAction;
private SceneController scene;
void Start () {
scene = SceneController.getInstance();
scene.setGameEventManager(this);
}
void Update () {
}
//hero逃離巡邏兵,得分
public void heroEscapeAndScore() {
if (myGameScoreAction != null)
myGameScoreAction();
}
//巡邏兵捕獲hero,遊戲結束
public void patrolHitHeroAndGameover() {
if (myGameOverAction != null)
myGameOverAction();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Patrols;
public class UserInterface : MonoBehaviour {
private IUserAction action;
void Start () {
action = SceneController.getInstance() as IUserAction;
}
void Update () {
detectKeyInput();
}
void detectKeyInput() {
if (Input.GetKey(KeyCode.UpArrow)) {
action.heroMove(Diretion.UP);
}
if (Input.GetKey(KeyCode.DownArrow)) {
action.heroMove(Diretion.DOWN);
}
if (Input.GetKey(KeyCode.LeftArrow)) {
action.heroMove(Diretion.LEFT);
}
if (Input.GetKey(KeyCode.RightArrow)) {
action.heroMove(Diretion.RIGHT);
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Com.Patrols {
public class Diretion {
public const int UP = 0;
public const int DOWN = 2;
public const int LEFT = -1;
public const int RIGHT = 1;
}
public class FenchLocation {
public const float FenchHori = 12.42f;
public const float FenchVertLeft = -3.0f;
public const float FenchVertRight = 3.0f;
}
public interface IUserAction {
void heroMove(int dir);
}
public interface IAddAction {
void addRandomMovement(GameObject sourceObj, bool isActive);
void addDirectMovement(GameObject sourceObj);
}
public interface IGameStatusOp {
int getHeroStandOnArea();
void heroEscapeAndScore();
void patrolHitHeroAndGameover();
}
public class SceneController : System.Object, IUserAction, IAddAction, IGameStatusOp {
private static SceneController instance;
private GameModel myGameModel;
private GameEventManager myGameEventManager;
public static SceneController getInstance() {
if (instance == null)
instance = new SceneController();
return instance;
}
internal void setGameModel(GameModel _myGameModel) {
if (myGameModel == null) {
myGameModel = _myGameModel;
}
}
internal void setGameEventManager(GameEventManager _myGameEventManager) {
if (myGameEventManager == null) {
myGameEventManager = _myGameEventManager;
}
}
/*********************實現IUserAction接口*********************/
public void heroMove(int dir) {
myGameModel.heroMove(dir);
}
/*********************實現IAddAction接口*********************/
public void addRandomMovement(GameObject sourceObj, bool isActive) {
myGameModel.addRandomMovement(sourceObj, isActive);
}
public void addDirectMovement(GameObject sourceObj) {
myGameModel.addDirectMovement(sourceObj);
}
/*********************實現IGameStatusOp接口*********************/
public int getHeroStandOnArea() {
return myGameModel.getHeroStandOnArea();
}
public void heroEscapeAndScore() {
myGameEventManager.heroEscapeAndScore();
}
public void patrolHitHeroAndGameover() {
myGameEventManager.patrolHitHeroAndGameover();
}
}
}
4.PatrolFactory.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Patrols;
namespace Com.Patrols {
public class PatrolFactory : System.Object {
private static PatrolFactory instance;
private GameObject PatrolItem;
private Vector3[] PatrolPosSet = new Vector3[] { new Vector3(-6, 0, 16), new Vector3(-1, 0, 19),
new Vector3(6, 0, 16), new Vector3(-5, 0, 7), new Vector3(0, 0, 7), new Vector3(6, 0, 7)};
public static PatrolFactory getInstance() {
if (instance == null)
instance = new PatrolFactory();
return instance;
}
public void initItem(GameObject _PatrolItem) {
PatrolItem = _PatrolItem;
}
public GameObject getPatrol() {
GameObject newPatrol = Camera.Instantiate(PatrolItem);
return newPatrol;
}
public Vector3[] getPosSet() {
return PatrolPosSet;
}
}
}
5.PatrolBehaviour.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Patrols;
//----------------------------------
// 此腳本加在巡邏兵上
//----------------------------------
public class PatrolBehaviour : MonoBehaviour {
private IAddAction addAction;
private IGameStatusOp gameStatusOp;
public int ownIndex;
public bool isCatching; //是否感知到hero
private float CATCH_RADIUS = 3.0f;
void Start () {
addAction = SceneController.getInstance() as IAddAction;
gameStatusOp = SceneController.getInstance() as IGameStatusOp;
ownIndex = getOwnIndex();
isCatching = false;
}
void Update () {
checkNearByHero();
}
int getOwnIndex() {
string name = this.gameObject.name;
char cindex = name[name.Length - 1];
int result = cindex - '0';
return result;
}
//檢測進入自己區域的hero
void checkNearByHero () {
if (gameStatusOp.getHeroStandOnArea() == ownIndex) { //只有當走進自己的區域
if (!isCatching) {
isCatching = true;
addAction.addDirectMovement(this.gameObject);
}
}
else {
if (isCatching) { //剛纔爲捕捉狀態,但此時hero已經走出所屬區域
gameStatusOp.heroEscapeAndScore();
isCatching = false;
addAction.addRandomMovement(this.gameObject, false);
}
}
}
void OnCollisionStay(Collision e) {
//撞擊圍欄,選擇下一個點移動
if (e.gameObject.name.Contains("Patrol") || e.gameObject.name.Contains("fence")
|| e.gameObject.tag.Contains("FenceAround")) {
isCatching = false;
addAction.addRandomMovement(this.gameObject, false);
}
//撞擊hero,遊戲結束
if (e.gameObject.name.Contains("Hero")) {
gameStatusOp.patrolHitHeroAndGameover();
Debug.Log("Game Over!");
}
}
}
6.HeroStatus.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Patrols;
//----------------------------------
// 此腳本加在主人公hero上
//----------------------------------
public class HeroStatus : MonoBehaviour {
public int standOnArea = -1;
void Start () {
}
void Update () {
modifyStandOnArea();
}
//檢測所在區域
void modifyStandOnArea() {
float posX = this.gameObject.transform.position.x;
float posZ = this.gameObject.transform.position.z;
if (posZ >= FenchLocation.FenchHori) {
if (posX < FenchLocation.FenchVertLeft)
standOnArea = 0;
else if (posX > FenchLocation.FenchVertRight)
standOnArea = 2;
else
standOnArea = 1;
}
else {
if (posX < FenchLocation.FenchVertLeft)
standOnArea = 3;
else if (posX > FenchLocation.FenchVertRight)
standOnArea = 5;
else
standOnArea = 4;
}
}
}
7.GameStatusText.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//----------------------------------
// 此腳本加在text上
//----------------------------------
public class GameStatusText : MonoBehaviour {
private int score = 0;
private int textType; //0爲score,1爲gameover
void Start () {
distinguishText();
}
void Update () {
}
void distinguishText() {
if (gameObject.name.Contains("Score"))
textType = 0;
else
textType = 1;
}
void OnEnable() {
GameEventManager.myGameScoreAction += gameScore;
GameEventManager.myGameOverAction += gameOver;
}
void OnDisable() {
GameEventManager.myGameScoreAction -= gameScore;
GameEventManager.myGameOverAction -= gameOver;
}
void gameScore() {
if (textType == 0) {
score++;
this.gameObject.GetComponent<Text>().text = "Score: " + score;
}
}
void gameOver() {
if (textType == 1)
this.gameObject.GetComponent<Text>().text = "Game Over!";
}
}
8.GameModel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Patrols;
public class GameEventManager : MonoBehaviour {
public delegate void GameScoreAction();
public static event GameScoreAction myGameScoreAction;
public delegate void GameOverAction();
public static event GameOverAction myGameOverAction;
private SceneController scene;
void Start () {
scene = SceneController.getInstance();
scene.setGameEventManager(this);
}
void Update () {
}
//hero逃離巡邏兵,得分
public void heroEscapeAndScore() {
if (myGameScoreAction != null)
myGameScoreAction();
}
//巡邏兵捕獲hero,遊戲結束
public void patrolHitHeroAndGameover() {
if (myGameOverAction != null)
myGameOverAction();
}
}
下面是在OOAction中
9.ISSActionCallback.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public enum SSActionEventType: int { Started, Completed }
public enum SSActionTargetType : int { Normal, Catching } //與原來不同的地方
public interface ISSActionCallback {
void SSActionEvent(SSAction source,
SSActionEventType eventType = SSActionEventType.Completed,
SSActionTargetType intParam = SSActionTargetType.Normal, //動作結束時回調,需要告知是哪種動作
string strParam = null,
Object objParam = null);
}
10.SSAction.cs
using UnityEngine;
using System.Collections;
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();
}
}
11.SSActionManager.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//併發順序
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 Start () {
}
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(kv.Key);
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 gameObj, SSAction action, ISSActionCallback manager) {
//先把該對象現有的動作銷燬(與原來不同部分)
for (int i = 0; i < waitingAdd.Count; i++) {
if (waitingAdd[i].gameObject.Equals(gameObj)) {
SSAction ac = waitingAdd[i];
waitingAdd.RemoveAt(i);
i--;
DestroyObject(ac);
}
}
foreach (KeyValuePair<int, SSAction> kv in actions) {
SSAction ac = kv.Value;
if (ac.gameObject.Equals(gameObj)) {
ac.destroy = true;
}
}
action.gameObject = gameObj;
action.transform = gameObj.transform;
action.callBack = manager;
waitingAdd.Add(action);
action.Start();
}
}
12.CCMoveToAction.cs
using System;
using System.Collections.Generic;
using UnityEngine;
public class CCMoveToAction: SSAction {
public Vector3 target;
public float speed;
public bool isCatching; //判定此動作是否爲追捕(與原來不同)
public static CCMoveToAction CreateSSAction(Vector3 _target, float _speed, bool _isCatching) {
CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();
action.target = _target;
action.speed = _speed;
action.isCatching = _isCatching;
return action;
}
public override void Start() {
}
public override void Update() {
this.transform.position = Vector3.MoveTowards(this.transform.position, target, speed);
if (this.transform.position == target) {
this.destroy = true;
if (!isCatching) //根據不同的動作類型回調函數傳遞不同的參數
this.callBack.SSActionEvent(this);
else
this.callBack.SSActionEvent(this, SSActionEventType.Completed, SSActionTargetType.Catching);
}
}
}
13.CCSequeneActions.cs
using System;
using System.Collections.Generic;
using UnityEngine;
//線性順序
public class CCSequeneActions : SSAction, ISSActionCallback {
public List<SSAction> actionList;
public int repeatTimes = -1; //序列動作重複次數
public int subActionIndex = 0; //順序動作裏某個動作的編號
public static CCSequeneActions CreateSSAction(List<SSAction> _actionList, int _repeatTimes = 0) {
CCSequeneActions action = ScriptableObject.CreateInstance<CCSequeneActions>();
action.repeatTimes = _repeatTimes;
action.actionList = _actionList;
return action;
}
public override void Start() {
foreach (SSAction action in actionList) {
action.gameObject = this.gameObject;
action.transform = this.transform;
action.callBack = this;
action.Start();
}
}
public override void Update() {
if (actionList.Count == 0)
return;
else if (subActionIndex < actionList.Count) {
actionList[subActionIndex].Update();
}
}
//提供給子動作回調,提醒動作序列執行下一個子動作
public void SSActionEvent(SSAction source,
SSActionEventType eventType = SSActionEventType.Completed,
SSActionTargetType intParam = SSActionTargetType.Normal, string strParam = null, object objParam = null) {
source.destroy = false;
this.subActionIndex++;
if (this.subActionIndex >= actionList.Count) {
this.subActionIndex = 0;
if (repeatTimes > 0)
repeatTimes--;
if (repeatTimes == 0) {
this.destroy = true;
this.callBack.SSActionEvent(this);
}
}
}
void OnDestroy() {
}
}
完啦