* 创建一个地图和若干巡逻兵(使用动画);
* 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
* 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
* 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
* 失去玩家目标后,继续巡逻;
* 必须使用订阅与发布模式传消息
* 工厂模式生产巡逻兵
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Dir { down, right, up, left}
public class PatrolData : MonoBehaviour {
// Use this for initialization
//巡逻兵的路线为一个正方形
public Vector3 startPostion; //巡逻的起始位置
public Vector3 endPostion;//正方形对角线位置
public int sideLength; //正方形边长
public int dir = 0;
public GameObject player; //玩家
public int sign; //巡逻兵在哪一块区域
}
PatrolFactory创建巡逻兵的工厂
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PatrolFactory : MonoBehaviour {
private List patrols = new List();
// Use this for initialization
public List GetPatrols()
{
int rectLength; //正方形边长
int[] pos_x = { 5, -2, -9 };
int[] pos_z = { 5, -2, -9 };
int index = 1;
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
Vector3 startPostion = new Vector3(pos_x[i], 0, pos_z[j]);
rectLength = UnityEngine.Random.Range(3, 5);
Vector3 endPostion = new Vector3(pos_x[i] + rectLength, 0, pos_z[j] + rectLength);
GameObject monster = Instantiate(Resources.Load("Prefabs/Monster"));
monster.transform.position = startPostion;
PatrolData data = monster.AddComponent();
data.startPostion = startPostion;
data.endPostion = endPostion;
data.sideLength = rectLength;
data.sign = index;
patrols.Add(monster);
++index;
}
}
return patrols;
}
}
巡逻兵追捕与巡逻动作
PatrolGoAction
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PatrolGoAction : SSAction {
private Vector3 start; //巡逻兵的起始位置
private Vector3 end;//巡逻兵起始位置的正方形对角线位置
private Vector3 next;
private int dir; //方向:0 x+, 1:z+, 2:x-,3:z-
// Use this for initialization
public static SSAction getPatrolGoAction()
{
PatrolGoAction action = ScriptableObject.CreateInstance();
return action;
}
public override void Start () {
PatrolData data = gameObject.GetComponent();
dir = 0;
start = data.startPostion;
end = data.endPostion;
// transform.localEulerAngles =new Vector3(0, 90, 0);
next = new Vector3(end.x,0,start.z);
transform.LookAt(next);
this.enable = true;
this.distroy = false;
}
// Update is called once per frame
public override void Update () {
//防止碰撞发生后的旋转
if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)
{
transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);
}
if (transform.position.y != 0)
{
transform.position = new Vector3(transform.position.x, 0, transform.position.z);
}
//移动
transform.position = Vector3.MoveTowards(transform.position, next, Time.deltaTime * 2f);
gameObject.GetComponent().SetBool("walk", true);
GameObject player = gameObject.GetComponent().player;
if (player !=null && player.GetComponent().area == gameObject.GetComponent().sign )
{
this.callback.SSActionEvent(this, 0, this.gameObject);
}
if (Vector3.Distance(transform.position, next) < 0.1)
{
dir = (dir + 1) % 4;
if (dir == 1)
{
next = new Vector3(end.x, 0, end.z);
}
else if (dir == 2)
{
next = new Vector3(start.x, 0, end.z);
}
else if (dir == 3)
{
next = new Vector3(start.x, 0, start.z);
}
else
{
next = new Vector3(end.x, 0, start.z);
}
transform.LookAt(next);
}
}
}
PatrolFollowAction
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PatrolFollowAction : SSAction {
public GameObject player;
// Use this for initialization
public override void Start () {
this.distroy = false;
this.enable = true;
}
// Update is called once per frame
public override void Update () {
//防止碰撞发生后的旋转
if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)
{
transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);
}
if (transform.position.y != 0)
{
transform.position = new Vector3(transform.position.x, 0, transform.position.z);
}
transform.LookAt(player.transform.position);
transform.position = Vector3.MoveTowards(transform.position, player.transform.position, Time.deltaTime * 1.5f);
gameObject.GetComponent().SetBool("walk", true);
player = gameObject.GetComponent().player;
if(player == null || player.GetComponent().area != gameObject.GetComponent().sign)
{
this.callback.SSActionEvent(this, 1, this.gameObject);
}
}
public static SSAction GetPatrolFollowAction(GameObject player)
{
PatrolFollowAction action = ScriptableObject.CreateInstance();
action.player = player;
return action;
}
}
PlayerData
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerData : MonoBehaviour {
public int area = 1; //玩家位于地图那一块区域
}
SSActionManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSActionManager : MonoBehaviour,ISSActionCallback {
protected Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
protected List waitingAdd = new List();
protected 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.distroy)
{
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 DestroyAllAction()
{
foreach (KeyValuePair<int, SSAction> kv in actions)
{
SSAction ac = kv.Value;
ac.gameObject.GetComponent().SetBool("walk", false);
ac.distroy = true;
}
}
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()
{
}
public void SSActionEvent(SSAction source, int intParam = 0, GameObject objectParam = null)
{
if (intParam == 0)
{
//跟踪玩家
source.distroy = true;
GameObject player = objectParam.GetComponent().player;
SSAction follow= PatrolFollowAction.GetPatrolFollowAction(player);
this.RunAction(objectParam,follow, this);
}else if(intParam == 1) {
//继续巡逻
source.distroy = true;
objectParam.GetComponent().player = null;
SSAction go = PatrolGoAction.getPatrolGoAction();
this.RunAction(objectParam, go, this);
}
}
}
PatrolActionManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PatrolActionManager : SSActionManager {
// Use this for initialization
public void StartGoAction(GameObject gameObject)
{
SSAction action = PatrolGoAction.getPatrolGoAction();
this.RunAction(gameObject, action, this);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EventPublisher : MonoBehaviour {
//分数实践
public delegate void ScoreEvent();
public static event ScoreEvent ScoreAddEvent;
public delegate void GameEvent();
public static event GameEvent GameOverEvent;
// Use this for initialization
public void ScoreAdd()
{
if(ScoreAddEvent!=null)
{
ScoreAddEvent();
}
}
public void GameOver()
{
if(GameOverEvent!=null)
{
GameOverEvent();
}
}
}
FirstSceneController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstSceneController : MonoBehaviour, SceneController,IUserAction {
private PatrolActionManager actionManger;
public bool game_over;
private ScoreRecorder recorder;
private UserGUI userGUI;
public EventPublisher publisher;
public GameObject player;
public GameObject map;
private List patrolsList;
public int area;
public void loadResources()
{
map = GameObject.Instantiate(Resources.Load("Prefabs/map"));
player = GameObject.Instantiate(Resources.Load("Prefabs/Player"));
player.AddComponent();
actionManger = gameObject.AddComponent();
recorder = gameObject.AddComponent();
publisher = gameObject.AddComponent();
userGUI = gameObject.AddComponent();
Director.getInstance().currentSceneController = this;
PatrolFactory patrols = gameObject.AddComponent();
patrolsList = patrols.GetPatrols();
}
private void Awake()
{
loadResources();
}
public void StartGame()
{
for (int i = 0; i < patrolsList.Count; ++i)
{
actionManger.StartGoAction(patrolsList[i]);
}
}
void Start () {
}
void Update () {
player.GetComponent().area = area;
}
private void OnEnable()
{
EventPublisher.ScoreAddEvent += AddScore;
EventPublisher.GameOverEvent += GameOver;
}
public void MovePlayer()
{
if(!game_over)
{
float horizontal = Input.GetAxis("Horizontal"); //A D 左右
float vertical = Input.GetAxis("Vertical"); //W S 上 下
player.transform.Translate(Vector3.forward * vertical * 3 * Time.deltaTime);//W S 上 下
if (vertical != 0)
{
player.GetComponent().SetBool("run", true);
}
else
{
player.GetComponent().SetBool("run", false);
}
player.transform.Rotate(0, horizontal * 50 * Time.deltaTime, 0);
}
}
void AddScore()
{
recorder.addRecord();
}
void GameOver()
{
game_over = true;
actionManger.DestroyAllAction();
}
public int GetScore()
{
return recorder.score;
}
}