先上游戏截图
把靶子调远一点,风力的影响会很明显
编码过程:
(1)利用一个空对象包含五个同心圆柱构建靶子
空对象的参数
一个同心圆柱的参数(其他的类似)
然后构造箭矢并制成预制(就是一个黄色的棍子= =)
(2)建立构造箭矢的工厂。这段代码根据之前的打飞碟的工厂修改,但是这里不需要回收。每次新建箭矢需要判断是否有挂载刚体,并将collider的trigger置为true
public int getFreeArrowId() {
for (int i = 0; i < arrowList.Count; i++) {
if (!arrowList[i].activeInHierarchy) {
return i;
}
}
GameObject temp = GameObject.Instantiate(arrow) as GameObject;
temp.SetActive(true);
if (temp.GetComponent<Rigidbody>() == null)
temp.AddComponent<Rigidbody>();
Component[] comp = temp.GetComponentsInChildren<CapsuleCollider>();
foreach (CapsuleCollider i in comp) {
i.enabled = true;
}
temp.GetComponent<CapsuleCollider>().isTrigger = true;
arrowList.Add(temp);
return arrowList.Count - 1;
}
public GameObject getFreeArrow(int id) {
if (id >= 0 && id < arrowList.Count) {
return arrowList[id];
}
return null;
}
(3)创建场景控制器。由于只有一个场景,因此这个类只有一个重要的方法就是发射箭矢
public void shootArrow(Vector3 dir) {
GameObject arrow = arrowFactory.getFreeArrow(arrowFactory.getFreeArrowId());
arrow.transform.position = new Vector3(0, 0, -10);
gameModel.shoot(arrow, dir);
}
(4)创建游戏场景。这个场景主要是对箭矢发射的实际实现和设置随机风力的方法
public void shoot(GameObject arrow, Vector3 dir) {
arrow.transform.up = dir;
arrow.GetComponent<Rigidbody>().velocity = dir * speed;
Force = Random.Range(-100, 100);
setWindForce(arrow);
}
private void setWindForce(GameObject arrow) {
arrow.GetComponent<Rigidbody>().AddForce(new Vector3(Force, 0, 0), ForceMode.Force);
}
public float getWindForce() {
return Force;
}
public string getWindDirection() {
if (Force < 0) {
return "Wind Direction : Left";
} else if (Force > 0) {
return "Wind Direction : Right";
} else {
return "Wind Direction : No Wind";
}
}
(5)
创建记分员。这里我利用传入的靶子的环的名字来加上对应的分数,也是设计为单例模式
public void countScore(string name) {
switch (name) {
case "C1":
score += 10;
break;
case "C2":
score += 8;
break;
case "C3":
score += 6;
break;
case "C4":
score += 4;
break;
case "C5":
score += 2;
break;
default:
break;
}
}
public int getScore() {
return score;
}
(6)然后构建GUI。这里设置显示风向、风力和分数,并根据鼠标点击的方向发射箭矢
void Start() {
sceneController = SceneController.getInstance();
scoreController = ScoreController.getInstance();
ScoreText.text = "Score : " + scoreController.getScore(); // 显示分数
}
// Update is called once per frame
void Update() {
WindDirectionText.text = sceneController.getGameModel().getWindDirection();
WindForceText.text = "Wind Force : " + sceneController.getGameModel().getWindForce(); // 显示风力
if (Input.GetMouseButtonDown(0)) {
Ray mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
sceneController.shootArrow(mouseRay.direction); //以点击的方向发射箭矢
}
ScoreText.text = "Score : " + scoreController.getScore(); // 显示分数
}
(7)编写箭矢的脚本。这里利用trigger的触发来传靶子环的名字以判断加分,并解除箭矢上的刚体,使得箭矢固定在与靶子碰撞的地方。
public class Arrow : MonoBehaviour {
private string Cname;
private ScoreController scoreController;
void OnTriggerEnter(Collider other) {
if (Cname == "") {
Cname = other.gameObject.name;
Destroy(GetComponent<Rigidbody>());
Component[] comp = GetComponentsInChildren<CapsuleCollider>();
foreach (CapsuleCollider i in comp) {
i.enabled = false;
}
GetComponent<CapsuleCollider>().isTrigger = false;
scoreController.countScore(Cname);
}
}
// Use this for initialization
void Awake() {
Cname = "";
scoreController = ScoreController.getInstance();
}
}
最后,除了最后一个脚本是挂载到箭矢预制上,其他的都挂载到main camera即可