視頻演示
智能巡邏兵
遊戲設計要求:
- 創建一個地圖和若干巡邏兵(使用動畫);
- 每個巡邏兵走一個3~5個邊的凸多邊型,位置數據是相對地址。即每次確定下一個目標位置,用自己當前位置爲原點計算;
- 巡邏兵碰撞到障礙物,則會自動選下一個點爲目標;
- 巡邏兵在設定範圍內感知到玩家,會自動追擊玩家;
- 失去玩家目標後,繼續巡邏;
- 計分:玩家每次甩掉一個巡邏兵計一分,與巡邏兵碰撞遊戲結束;
程序設計要求:
- 必須使用訂閱與發佈模式傳消息
- subject:OnLostGoal
- Publisher: ?
- Subscriber: ?
- 工廠模式生產巡邏兵
效果截圖
具體實現
重要代碼如下:
Patrol類
public class Patrol :MonoBehaviour
{
public enum PatrolState { PATROL,FOLLOW};
public int sign; //the patrol in which area
public bool isFollowPlayer = false;
public GameObject player=null; //the player
public Vector3 startPos,nextPos;
private float minPosX,minPosZ; // the range of this patrol can move;
private bool isMoving = false;
private float distance;
private float speed = 1.2f;
PatrolState state = PatrolState.PATROL;
private void Start()
{
minPosX = startPos.x - 2.5f;
minPosZ = startPos.z - 2.5f;
isMoving = false;
AreaCollide.canFollow += changeStateToFollow;
}
public void FixedUpdate()
{
if((SSDirector.getInstance().currentScenceController as FirstController).gameState == GameState.END)
{
return;
}
if(state == PatrolState.PATROL)
{
GoPatrol();
}
else if(state == PatrolState.FOLLOW)
{
Follow();
}
}
public void GoPatrol()
{
if (isMoving)
{
transform.position = Vector3.MoveTowards(this.transform.position, nextPos, speed * Time.deltaTime);
distance = Vector3.Distance(this.transform.position, nextPos);
if(distance < 0.5)
{
isMoving = false;
}
return;
}
float posX = Random.Range(0f, 5f);
float posZ = Random.Range(0f, 5f);
nextPos = new Vector3(minPosX+posX, 0, minPosZ+posZ);
isMoving = true;
}
public void Follow()
{
if(player != null)
{
nextPos = player.transform.position;
transform.position = Vector3.MoveTowards(this.transform.position, nextPos, speed * Time.deltaTime);
}
}
public void changeStateToFollow(int sign_,bool isEnter)
{
if(sign == sign_ )
{
if (isEnter)
{
state = PatrolState.FOLLOW;
player = (SSDirector.getInstance().currentScenceController as FirstController).player;
isFollowPlayer = true;
}
else
{
isFollowPlayer = false;
state = PatrolState.PATROL;
player = null;
isMoving = false;
}
}
}
}
巡邏兵工廠
public class PatrolFactory:MonoBehaviour
{
private List<GameObject> used = new List<GameObject>(); // the used patrol
private Vector3[] PatrolPos = new Vector3[3];
private bool isProduce = false;
FirstController firstController;
private void Start()
{
firstController = SSDirector.getInstance().currentScenceController as FirstController;
}
public List<GameObject> GetPatrols()
{
firstController = SSDirector.getInstance().currentScenceController as FirstController;
if (!isProduce)
{
int index = 0;
float[] posZ = { 3.75f, -3.75f };
float[] posX = { 3.75f, -3.75f };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
if(posX[j] > 0 && posZ[i] > 0)
{
continue;
}
PatrolPos[index++] = new Vector3(posX[j], 0, posZ[i]);
}
}
for (int i = 0; i < 3; i++)
{
GameObject patrol = Instantiate(Resources.Load<GameObject>("Prefabs/Patrol"));
patrol.transform.parent = firstController.plane.transform;
patrol.transform.position = PatrolPos[i];
patrol.GetComponent<Patrol>().sign = i + 1;
patrol.GetComponent<Patrol>().startPos = PatrolPos[i];
used.Add(patrol);
}
isProduce = true;
}
return used;
}
public void destoryFactory()
{
foreach(var a in used)
{
DestroyImmediate(a);
}
used = new List<GameObject>();
isProduce = false;
}
}
場景障礙物
public class AreaCollide : MonoBehaviour
{
public int sign;
public delegate void CanFollow(int state,bool isEnter);
public static event CanFollow canFollow;
public delegate void AddScore();
public static event AddScore addScore;
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.tag == "Player")
{
canFollow(sign,true);
}
}
private void OnTriggerExit(Collider collider)
{
if (collider.gameObject.tag == "Player")
{
canFollow(sign,false);
addScore();
}
}
}