Unity3D——射箭游戏

先上游戏截图




把靶子调远一点,风力的影响会很明显




编码过程:

(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即可




  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值