简介
就是。。一个简单的射靶游戏, 有随机的风向,越接近靶心分数越高。
对象处理
我们。。需要一支箭和一个靶。。
靶由5个圆柱体拼接而成,然后在父对象那里挂载刚体主件,5个子对象分别挂载mesh collider组件
箭由箭头(圆柱体),箭身(圆柱体),箭尾(两个相交的平面)构建而成
同样,父对象挂刚体,子对象挂碰撞器,然后。。我们就可以写代码啦。。
UML
其实这个UML图跟上次的打飞碟的 UML图大同小异,就把Disk改为Arrow就行啦
代码
这里就只展示跟之前不同的部分
DiskData对应ArrowScript
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowScript : MonoBehaviour {
public string shootring;
private ScoreRecorder recorder;
void OnTriggerEnter(Collider other) {
shootring = other.gameObject.tag;
Destroy(GetComponent<Rigidbody>());
recorder.Record(shootring);
}
void Awake() {
recorder = (ScoreRecorder)FindObjectOfType(typeof(ScoreRecorder));
}
}
记分系统稍微改改
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScoreRecorder : MonoBehaviour {
private float score;
public float getScore() {
return score;
}
public void Record(string target_ring) {
switch (target_ring) {
case "Ring10": score += 10; break;
case "Ring8": score += 8; break;
case "Ring6": score += 6; break;
case "Ring4": score += 4; break;
case "Ring2": score += 2; break;
}
}
public void Reset() {
score = 0;
}
}
UI加入风速
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public interface IUserAction {
void shoot();
}
public class UserGUI : MonoBehaviour {
private IUserAction action;
private float width, height;
private string countDownTitle;
public RoundActionManager actionmanager;
void Start() {
countDownTitle = "Start";
action = Director.getInstance().currentSceneController as IUserAction;
}
float castw(float scale) {
return (Screen.width - width) / scale;
}
float casth(float scale) {
return (Screen.height - height) / scale;
}
void OnGUI() {
width = Screen.width / 12;
height = Screen.height / 12;
GUI.Label(new Rect(castw(2f)+20, casth(6f) - 20, 50, 50), ((RoundController)Director.getInstance().currentSceneController).leaveSeconds.ToString());
GUI.Button(new Rect(580, 10, 80, 30), ((RoundController)Director.getInstance().currentSceneController).scoreRecorder.getScore().ToString());
if (Director.getInstance().currentSceneController.state != State.WIN && Director.getInstance().currentSceneController.state != State.LOSE
&& GUI.Button(new Rect(10, 10, 80, 30), countDownTitle)) {
if (countDownTitle == "Start") {
countDownTitle = "Pause";
Director.getInstance().currentSceneController.Resume();
} else {
countDownTitle = "Start";
Director.getInstance().currentSceneController.Pause();
}
}
if (Director.getInstance().currentSceneController.state == State.WIN) {
if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Win!")) Director.getInstance().currentSceneController.Restart();
} else if (Director.getInstance().currentSceneController.state == State.LOSE) {
if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Lose!")) Director.getInstance().currentSceneController.Restart();
}
}
public Text windforce;
public Text winddirection;
void Update() {
action.shoot();
float force = actionmanager.getWindForce();
if (force < 0)
winddirection.text = "风向 : 左";
else if (force > 0)
winddirection.text = "风向 : 右";
else
winddirection.text = "风向 : 无";
windforce.text = "风力 : " + actionmanager.getWindForce();
action.shoot();
}
}
动作管理器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoundActionManager : SSActionManager, ISSActionCallback {
public RoundController scene;
private float speed = 20.0f;
private float force = 0f;
public void shootArrowAction(GameObject arrow, Vector3 dir) {
arrow.transform.position = new Vector3(0, 0, -9);
arrow.transform.up = dir;
arrow.GetComponent<Rigidbody>().velocity = dir * speed;
}
public void wind(GameObject arrow, float time) {
if(time % 2 == 0) force = UnityEngine.Random.Range(-30, 30);
if(arrow != null && arrow.GetComponent<Rigidbody>() != null) {
arrow.GetComponent<Rigidbody>().AddForce(new Vector3(force, 0, 0), ForceMode.Force);
}
}
public float getWindForce() {
return force;
}
protected void Start() {
scene = (RoundController)Director.getInstance().currentSceneController;
scene.actionManager = this;
}
protected new void Update() {
base.Update();
}
public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,
int intParam = 0,
string strParam = null,
Object objectParam = null) {
}
}
控制器
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum State { WIN, LOSE, PAUSE, CONTINUE, START };
public class RoundController : MonoBehaviour, IUserAction, ISceneController {
public ArrowFactory arrowFactory;
public RoundActionManager actionManager;
public ScoreRecorder scoreRecorder;
public List<GameObject> arrow;
public GameObject new_arrow;
public GameObject target;
public State state { get; set; }
public int leaveSeconds;
IEnumerator DoCountDown() {
while (leaveSeconds >= 0) {
yield return new WaitForSeconds(1);
leaveSeconds--;
}
}
void Awake() {
Director director = Director.getInstance();
director.setFPS(60);
director.currentSceneController = this;
Director.getInstance().currentSceneController.state = State.PAUSE;
arrowFactory = Singleton<ArrowFactory>.Instance;
scoreRecorder = Singleton<ScoreRecorder>.Instance;
state = State.PAUSE;
leaveSeconds = 60;
}
void Start () {
actionManager = GetComponent<RoundActionManager>() as RoundActionManager;
LoadResources();
}
void Update() {
RecycleArrow ();
Judge();
}
private void FixedUpdate() {
actionManager.wind(new_arrow, leaveSeconds);
}
public void LoadResources() {
Camera.main.transform.position = new Vector3(0, 0, -10);
target = GameObject.Instantiate(Resources.Load("Prefabs/Target")) as GameObject;
target.transform.position = new Vector3(0, 0, 3);
}
public void shoot() {
if (Input.GetMouseButtonDown(0) && (state == State.START || state == State.CONTINUE)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
new_arrow = arrowFactory.GetArrow();
arrow.Add(new_arrow);
actionManager.shootArrowAction(new_arrow, ray.direction);
}
}
public void RecycleArrow() {
for(int i = 0; i < arrow.Count; i++) {
if(arrow[i].transform.position.y < -10 || arrow[i].transform.position.z > 15) {
arrowFactory.FreeArrow(arrow[i]);
arrow.Remove(arrow[i]);
}
}
}
public void Judge() {
if (leaveSeconds == 0 && scoreRecorder.getScore() < 100) {
StopAllCoroutines();
state = State.LOSE;
}
else if ((leaveSeconds > 0 && scoreRecorder.getScore() >= 100)) {
StopAllCoroutines();
state = State.WIN;
}
}
public void Pause() {
state = State.PAUSE;
StopAllCoroutines();
for (int i = 0; i < arrow.Count; i++) {
arrow [i].SetActive (false);
}
}
public void Resume() {
StartCoroutine(DoCountDown());
state = State.CONTINUE;
for (int i = 0; i < arrow.Count; i++) {
arrow[i].SetActive(true);
}
}
public void Restart() {
scoreRecorder.Reset();
Application.LoadLevel(Application.loadedLevelName);
Director.getInstance().currentSceneController.state = State.START;
}
}
工厂模式
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowFactory : MonoBehaviour {
private List<GameObject> used = new List<GameObject>();
private List<GameObject> free = new List<GameObject>();
public GameObject GetArrow() {
GameObject a_arrow;
if (free.Count > 0) {
a_arrow = free[0];
free.Remove(free[0]);
} else {
a_arrow = GameObject.Instantiate(Resources.Load("prefabs/Arrow")) as GameObject;
}
a_arrow.SetActive(true);
used.Add(a_arrow);
return a_arrow;
}
public void FreeArrow(GameObject disk) {
for(int i = 0; i < used.Count; i++) {
if(used[i] == disk) {
disk.SetActive(false);
used.Remove(used[i]);
free.Add(disk);
}
}
}
}
大概就这么多啦,还是得说一句。。这个框架实在是好用。