3D游戏编程与设计 Week8

这次的作业是跟着这位师兄:@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();
    }
}


2.UserInterface.cs
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);
        }
    }
}


3.SceneController.cs
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() {

    }
}


完啦微笑
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值